How to use parametrized member function of a struct in callback? - gtk3

I have a struct that looks like the one below
struct dc_callback
{
int
my_configure_event(
GtkWidget *widget,
GdkEventConfigure *event,
struct LoadData *myData)
{
...others
return TRUE;
}
//Parametrized Constructor
int
my_draw(
GtkWidget *widget,
cairo_t *cr,
struct LoadData *myData)
{
...others
return TRUE;
}
};
It has two parametrized member function that I intend to call from g_signal_connect for some nth time.
main(){
int i;
dc_callback dc_callback_instance[nth];
for(i=0;i<nth;i++){
g_signal_connect(widget_list[i],"draw",G_CALLBACK(dc_callback_instance[i].my_draw),myData);
g_signal_connect(widget_list[i],"configure-event",G_CALLBACK(dc_callback_instance[i].my_configure_event),myData);
}
}
However, during compile time, I get an error regarding invalid use of member function int dc_callback::my_draw(args). It ask me to add () but that could not be done since the G_CALLBACK accepts function name without its attached argument.
How to I accomplish this?

The answer of #0x5453 is correct except for my_draw_cbk and its call : it shall be
gboolean my_draw_cbk ( GtkWidget *widget,
cairo_t *cr,
struct CallbackData *cbData)
{
cbData->dc_callback_inst.my_draw(widget, cr, cbData->otherData);
return TRUE;
}
and to connect the signal :
// cbData shall be free with g_free when no longer needed
CallbackData* cbData = g_new(CallbackData, 1);
// set the cbData values..
g_signal_connect(widget_list[i],"draw",G_CALLBACK(my_draw_cb),cbData);

G_CALLBACK expects a (non-member) function pointer, and you are not using the proper syntax for passing a function pointer. However, there is a bigger issue: Function pointers and member function pointers are different concepts in C++. You cannot pass a member function pointer to an interface that expects a standard function pointer.
So, how to associate the invocation of the callback with your dc_callback instance?
Traditionally when working with C-style API's, you have to provide a free function for the callback that takes your instance (and any extra data) as a void* parameter. Then inside the callback, you can cast the void* back to the original type. In your case, this could look something like:
struct CallbackData {
dc_callback& dc_callback_inst;
Foo otherData; // whatever else you need to capture here
};
void my_draw_cb(void* data) { // g_signal_connect might pass more params to cb in addition to data
CallbackData& cbData = *(CallbackData*)data;
cbData->dc_callback_inst.my_draw(cbData->otherData);
}
// ...
for(i=0;i<nth;i++){
CallbackData cbData{dc_callback_instance[i], myData};
g_signal_connect(widget_list[i],"draw",G_CALLBACK(&my_draw_cb),cbData);
// ...
}

Related

How come arrow function can by pass the Function signature when assigned?

I can assign an arrow function, which returns a value to a function variable that requires a void signature. But I can not assign a block function that returns a value. Why? Should the not be arrow function restricted as well, as it returns a value?
arrow function
block function
That is because by doing
void Function(int) function=(a)=>b=a;
Dart assumes that you don't want to return the value of the assignation, that normally you could use, for example:
void main() {
int a=10,b;
print(b=a);
}
So, dart just thinks that you want to assign the variable, nothing more. Another more detailed example here:
int number=10;
late int target;
void main() {
print(test());
number+=10;
test2();
print(target);
}
int test()=>target=number;
void test2()=>target=number;
//Note: there aren't many best practices here (For example, global variables)
//Is just an example to make you understand, nothing more
but if you specify the return, dart will think you reeeeally want to return that value, and that's not possible, as it is a void function.

Dart/Flutter ffi (Foreign Function Interface) native callbacks eg: sqlite3_exec

Hello I am using dart:ffi to build an interface with my native c/c++ library.
and I needed a way to get a callback from c to dart as an example in sqlite:
int sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
void *, /* 1st argument to callback */
char **errmsg /* Error msg written here */
);
the third parameter in sqlite3_exec is function pointer to a callback.
so if I called this function in dart using ffi I need to pass a function pointer: and in dart:ffi Pointer class there is a function named fromFunction witch accepts a dart static function and an exceptionalReturn; but just by calling this function to get the function pointer of a dart managed function: a (sigterm) is raised and the dart code no long work in the process.
So My Question: Is there any way to get a native callback in dart, as in Python, c#, ..
Extra:
Is there any way to include dartino in a flutter project, since this ForeignDartFunction covers what I need.
I got an example to work. Hopefully you can adapt this to your case.
Example C function
EXTERNC int32_t foo(
int32_t bar,
int32_t (*callback)(void*, int32_t)
) {
return callback(nullptr, bar);
}
Dart code
First the typedefs. We need two for the native function foo and one for the Dart callback.
typedef example_foo = Int32 Function(
Int32 bar, Pointer<NativeFunction<example_callback>>);
typedef ExampleFoo = int Function(
int bar, Pointer<NativeFunction<example_callback>>);
typedef example_callback = Int32 Function(Pointer<Void>, Int32);
and the code for the callback
static int callback(Pointer<Void> ptr, int i) {
print('in callback i=$i');
return i + 1;
}
and the lookup
ExampleFoo nativeFoo =
nativeLib.lookup<NativeFunction<example_foo>>('foo').asFunction();
and, finally, use it like this:
int foo(int i) {
return nativeFoo(
i,
Pointer.fromFunction<example_callback>(callback, except),
);
}
as expected, foo(123) prints flutter: in callback i=123 and returns 124

va_arg prevents me from calling a managed delegate in a native callback

In a C++/CLI assembly, I'm trying to call a managed delegate from a native callback. I followed Doc Brown's answer here, and my implementation so far looks like this:
The native callback - ignore the commented out parts for now:
static ssize_t idaapi idb_callback(void* user_data, int notification_code, va_list va)
{
switch (notification_code)
{
case idb_event::byte_patched:
{
//ea_t address = va_arg(va, ea_t);
//uint32 old_value = va_arg(va, uint32);
return IdaEvents::BytePatched(0, 0);
}
break;
}
return 0;
}
As you can see above, I call this managed delegate instantiated in a static class:
public delegate int DatabaseBytePatchedHandler(int address, int originalValue);
private ref class IdaEvents
{
static IdaEvents()
{
BytePatched = gcnew DatabaseBytePatchedHandler(&OnDatabaseBytePatched);
}
public: static DatabaseBytePatchedHandler^ BytePatched;
private: static int OnDatabaseBytePatched(int address, int originalValue)
{
return 0;
}
};
This compiles fine. But the code is incomplete - remember the commented out part in the native callback above? I actually have to retrieve the values from the va_list passed to the callback, and pass those on to my managed delegate:
ea_t address = va_arg(va, ea_t);
uint32 old_value = va_arg(va, uint32);
return IdaEvents::BytePatched(address, old_value);
But as soon as I uncomment one of the lines using va_arg, I cannot compile the project anymore and retrieve the following errors marking the line where I call the managed delegate:
C3821 'IdaEvents': managed type or function cannot be used in an unmanaged function
C3821 'IdaEvents::BytePatched': managed type or function cannot be used in an unmanaged function
C3821 'BytePatched': managed type or function cannot be used in an unmanaged function
C3821 'DatabaseBytePatchedHandler::Invoke': managed type or function cannot be used in an unmanaged function
C3642 'int DatabaseBytePatchedHandler::Invoke(int,int)': cannot call a function with __clrcall calling convention from native code
C3175 'DatabaseBytePatchedHandler::Invoke': cannot call a method of a managed type from unmanaged function 'idb_callback'
This really confuses me. Why is the compiler suddenly acting up as soon as I try to use va_arg? Even a single line without any assignment causes this error to pop up.
Am I thinking too naive here? I'm obviously missing a piece of the puzzle, and any help supporting me in finding it is greatly appreciated.

PowerRegisterSuspendResumeNotification - provided callback function doesn't work as expected

I register my application to receive notification when the system is suspended or resumed.
MSDN documentation
Function I'd like to be executed after application receives notification (I tried both void and void CALLBACK and both work same way):
void isConnectedStandby()
{
printf( "ConnectedStandby Request");
}
1st case - I provide pointer to the isConnectedStandby function, but system treats as a double pointer to the function - it calls an address which is under this callback pointer.
HPOWERNOTIFY RegistrationHandle;
PowerRegisterSuspendResumeNotification(
DEVICE_NOTIFY_CALLBACK,
&isConnectedStandby,
&RegistrationHandle
);
2nd case - here I provide as follows (this way my function code is executed):
typedef void (*StatusFunction_t)();
StatusFunction_t StatusFunction = isConnectedStandby;
HPOWERNOTIFY RegistrationHandle;
PowerRegisterSuspendResumeNotification(
DEVICE_NOTIFY_CALLBACK,
&isConnectedStandby,
&RegistrationHandle
);
System calls not only mine function, but all addresses after the first one (if I provide an array of functions, it executes one after another to crash when there is no valid code available)
What is the correct way to use this function?
Function declaration (must be static ULONG with 3 parameters as you can see below):
static ULONG isConnectedStandby(PVOID Context, ULONG Type, PVOID Setting);
ULONG isConnectedStandby(PVOID Context, ULONG Type, PVOID Setting)
{
printf( "ConnectedStandby Request");
return 0;
}
Istead of providing callback function directly to PowerRegisterSuspendResumeNotification we have to provide struct _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS filled with our functions address :
static _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS testCallback = {
isConnectedStandby,
nullptr
};
HPOWERNOTIFY RegistrationHandle;
PowerRegisterSuspendResumeNotification(
DEVICE_NOTIFY_CALLBACK,
&testCallback,
&RegistrationHandle
);
MSDN documentation did not mention any of those information.

Using boost::program_options with own template class possible?

I'm currently start using boost::program_options for parsing command line options as well as configuration files.
Is it possible to use own template classes as option arguments? That means, something like
#include <iostream>
#include "boost/program_options.hpp"
namespace po = boost::program_options;
template <typename T>
class MyClass
{
private:
T* m_data;
size_t m_size;
public:
MyClass( size_t size) : m_size(size) { m_data = new T[size]; }
~MyClass() { delete[] m_data; }
T get( size_t i ) { return m_data[i]; }
void set( size_t i, T value ) { m_data[i] = value; }
};
int main (int argc, const char * argv[])
{
po::options_description generic("General options");
generic.add_options() ("myclass", po::value< MyClass<int>(2) >(),
"Read MyClass");
return 0;
}
Trying to compile this I get an Semantic Issue (No matching function for call to 'value'). I guess I need to provide some casting to an generalized type but I have no real idea.
Can anybody help?
Thanks
Aeon512
I wouldn't know if boost::program_options allows the use-case you are trying, but the error you are getting is because your are trying to pass an object as a template type to po::value<>. If the size is known at compile-time, you could have the size be passed in as a template parameter.
template< typename T, size_t size >
class MyClass {
T m_data[size];
public:
// ...
};
And then use it like so:
po::value< MyClass<int, 2> >()
You should also look into using Boost.Array instead that I guess fulfills what you are trying to implement.
I would write it like this:
MyClass<int> mine(2);
generic.add_options() ("myclass", po::value(&mine), "Read MyClass");
Then all that needs to be done is to define an input stream operator like this:
std::istream& operator >>(std::istream& source, MyClass& target);
Then Boost Program Options will invoke this stream operator when the myclass option is used, and your object will be automatically populated according to that operator's implementation, rather than having to later call one of the Program Options functions to extract the value.
If you don't prefer the above syntax, something like should work too:
generic.add_options() ("myclass", po::value<MyClass<int> >()->default_value(MyClass<int>(2)), "Read MyClass");
This way you would be creating the instance of your class directly with your desired constructor argument outside of the template part where runtime behavior isn't allowed. I do not prefer this way because it's verbose and you end up needing to call more functions later to convert the value.