In a C function declaration, I have seen this parameter definition:
void *userData
so, what exactly is that? My guess: the void says it can be anything arbitrary, or even nothing. Almost similar to id of objective-c. It just allows to pass in whatever data structure you like.
The star in front of userData says, that the argument must be passed in by reference.
So when using this stuff in the function body, typically it must be casted and dereferenced.
So if I pass in an pointer to SomeClass instance, I would get that like this:
SomeClass *myObj = (SomeClass*)userData;
In the case I had nothing special to pass along, I would provide NULL as argument.
Are my assumptions correct? Or did I get something wrong?
A void * is a pointer to a structure of unknown type. You can think of it as "a pointer to anything". It's not the same as Objective-C's id type, which is the type of any object. An id looks like this:
typedef struct objc_object {
Class isa;
} *id;
Typically in Objective-C (and I'm sure in C too) a framework might use some callback to tell you something. That callback will often take a parameter containing data that you give it - perhaps the object that started the action, and that needs to know that something's happened. A void * parameter lets the framework define a callback without depending on your code, so you can put anything you like into the callback. (Of course that means you also have to ensure that you cast your void *userData back into the appropriate type.)
void * means pointer to anything. So, you could pass anything "by reference" via void * argument. userData parameter name suggests (but is only a suggestion so it may vary across various APIs), that this argument is some arbitrary user-supplied data. That is, function in question will do nothing with it, just store, and give you it back some time. For example, in GTK+ you can attach a callback to some event. You can pass your own data to g_signal_connect as user_data argument, and in event handler, GTK+ will pass you your data back:
GtkWidget *button = gtk_button_new ();
const char *data = "Hello World;)";
g_signal_connect (button, "clicked", on_clicked, data);
(...)
void on_clicked (GtkWidget *widget, void * data)
{
const char *text = (const char *)data;
printf ("%s\n", text); // will print "Hello World;)"
}
void * is a pointer to any data type.
Note that it is not necessarily the right size for a pointer to a function.
Without seeing the actual code I'm guessing the parameter belongs to a function which takes a callback? If so it is probably a piece of context which, as you say, you can set to whatever you want. When the function invokes your callback it will pass this context along, which means you don't need a global to store this data.
Your understanding is essentially correct, although it is called a pointer not a reference. This is usually a mechanism for letting users "extend" a data structure by passing in a block of any type of data. An example I have seen this used is for nodes of a tree display in a GUI. The GUI framework adds the void pointer so that when a user clicks a node of this tree, you can pull more meaningful information about the node than just its name into your calling routine. Since only you know what type of data would be meaningful to your application, the type is simply a void*.
Also note that you are almost always responsible for managing the memory for userData.
Related
In Go source I have
type T struct {
// some data
}
func (t *T)M(arg0 SomeType1) {
// some computations
}
var Obj *T
In C sources I have
// SomeType1C is equivalent to SomeType1.
typedef void (*CallbackFunc)(SomeType1C);
// callback will be called !after! register_callback function returns.
void register_callback(CallbackFunc callback);
I would like to use Obj.M as callback for register_callback in C.
On MS Windows for winapi I pass smth like C.CallbackFunc(unsafe.Pointer(syscall.NewCallback(Obj.M))) to register_callback for this (not sure is it fully correct, but at least this works). But where is no NewCallback for non-Windows systems.
PS:
I'm sure that callback is registered after T is initialised and removed before T is removed.
I may have multiple instances of T and some of them may be used to callback's 'source' at same time (so T is not some kind of singltone).
Function pointer callbacks in GoLang's wiki uses gateway function, but I don't see how to adequate use it with struct's method.
Base idea:
Use exported callback as a proxy between C and Go:
//export callback
func callback(data0 SomeType1C, data1 Data){ // data1 - data passed to register_callback_with_data
obj := convertDataToObj(data1)
obj.M(data0)
}
and register it like this:
register_callback_with_data(callback, convertObjToData(obj));
Where are 3 ways: wrong (and easy), limited (medium) and right (hard).
Wrong (and easy) way:
Pass pointer to Go struct into C (as in original answer). This is totally wrong because Go runtime can move struct in memory. Usually this operation is transparent (all Go pointers will be updated automatically). But pointers in C memory to this struct will not be updated and program may crash/UB/... when tries to use it. Do not use this way.
Limited (medium) way:
Similar to previous, but with Go struct allocated in C memory:
Obj = (*T)(C.calloc(C.size_t(unsafe.Sizeof(T{}))))
In this case Obj can not be moved by Go runtime because it is in C memory. But now if Obj has pointers to Go memory (fields with *-variables, maps, slices, channels, function-pointers, ...) then this also may cause crash/UB/... This is because:
if there are no (other) Go pointers to the same variable (memory), then Go runtime thinks that this memory is free and can be reused,
or, if there is other Go pointer to same variable (memory), then Go can move this variable in memory.
So, use this way only if struct has no pointers to Go memory. Usually this means that struct contains only primitive fields (ints, floats, bool).
Right (and hard) way:
Assign id (of integer type for example) for each object of type T and pass this id into C. In exported callback you should convert id back to object. This is right way with no limitation, so this way may be used always. But this way requires to maintain some array/slice/map to convert between objects and ids. Moreover, this convertation may require some synchronization for thread-safe (so see sync.Mutex and sync.RWMutex).
Original answer:
Not best answer and has restrictions, but no other suggested. In my case I can pass additional data to register_callback. This data will be passed back to callback on each call. So I pass unsafe.Pointer(Obj) as data and use gateway function:
//export callback
func callback(data SomeType1C, additionalData unsafe.Pointer){
obj := (*T)(additionalData) // Get original Obj (pointer to instance of T)
dataGo := *(*SomeType1)(unsafe.Pointer(&data)) // Cast data from C to Go type
obj.M(dataGo)
}
and register it like this:
register_callback_with_data(callback, unsafe.Pointer(Obj));
PS: but still want to know how to do this better in general case (without additional data).
I've recently inherited some (undocumented) C code that contains several instances of this pattern:
void my_function(void *_foo, const void *_bar) {
MyType *foo = (MyType *)_foo;
MyType *bar = (MyType *)_bar;
I'm pretty familiar with C but I can't for the life of me figure out why the function consumes void pointers. Isn't this just going to suppress potentially helpful compiler warnings if the wrong type is passed in anywhere? Or is there a sensible method behind it that I am new to?
Generally, the void * is used as an abstraction i.e. you can pass pointers of different types using void * to a function and later depending on appropriate conditions, you can typecast the void * to the correct type and use it.
Another usage could be when the calling function is in a logically separate unit like a library and doesn't have access to the correct type to which the pointer belongs. But, still the data has to pass through that function.
I used to use such abstraction mechanisms with callbacks. For Example, if I am calling a library which function which eventually calls my callback and I want some data of application in my callback, but, the library function has no use of it, then I will pass such data typecasted as void * to the library function and on receiving that data in the callback, I will typecast it to appropriate type and use it.
I have a function that is connected to the "changed" signal for a combobox in gtk, which in turn calls another function read_button_config.
The read_button_config takes the main window, a combobox and a vcontainer which I had not declared globally as parameters
Which way is better for passing these parameters:
- declaring the parameters globally
- passing the parameters as a struct to the first function, and passing the struct members to the read_button_config function?
Please let me know why you think either is better, I want to know what is a better way for future development
Which way is better for passing these parameters: - declaring the
parameters globally - passing the parameters as a struct to the first
function, and passing the struct members to the read_button_config
function?
The latter is the preferred way; that is the purpose of the user_data parameter to signal functions, after all.
Declaring them globally isn't bad. Rather, using the user_data is idiomatic. It's a bit harder since you have to manage the memory for the user_data yourself, but using user_data keeps your code modules more self-contained. You will need to decide what you want to do.
– andlabs
I'm writing a wrapper around a C library in Objective-C. The library allows me to register callback functions when certain events occur.
The register_callback_handler() function takes a function pointer as one of the parameters.
My question to you gurus of programming is this: How can I represent an Objective-C method call / selector as a function pointer?
Would NSInvocation be something useful in this situation or too high level?
Would I be better off just writing a C function that has the method call written inside it, and then pass the pointer to that function?
Any help would be great, thanks.
Does register_callback_handler() also take a (void*) context argument? Most callback APIs do.
If it does, then you could use NSInvocation quite easily. Or you could allocate a little struct that contains a reference to the object and selector and then cobble up your own call.
If it only takes a function pointer, then you are potentially hosed. You need something somewhere that uniquely identifies the context, even for pure C coding.
Given that your callback handler does have a context pointer, you are all set:
typedef struct {
id target;
SEL selector;
// you could put more stuff here if you wanted
id someContextualSensitiveThing;
} TrampolineData;
void trampoline(void *freedata) {
TrampolineData *trampData = freedata;
[trampData->target performSelector: trampData->selector withObject: trampData-> someContextualSensitiveThing];
}
...
TrampolineData *td = malloc(sizeof(TrampolineData));
... fill in the struct here ...
register_callback_handler(..., trampoline, td);
That is the general idea, anyway. If you need to deal with non-object typed arguments and/or callbacks, it gets a little bit trickier, but not that much. The easiest way is to call objc_msgSend() directly after typecasting it to a function pointer of the right type so the compiler generates the right call site (keeping in mind that you might need to use objc_msgSend_stret() for structure return types).
I have a C function named SetParams(...) with a variable number of arguments. This function sets up a static data structure (let us name it Data). SetParams is used with pairs of arguments, e.g. SetParams("paramA", paramA_value, "paramB", paramB_value) etc. It can also be called many times, e.g.
SetParams("paramA", paramA_value);
SetParams("paramB", paramB_value);
...
When all 'parameters' have been set, another function is called (let us name it Execute) that takes no args:
Execute();
// uses data from static 'Data' and performs error_handling and execution
I was wondering if I could structure this kind of code in a more object-oriented way. So, I would like some advice, especially for error-handling, since some pairs of args may contradict others.
The general practice for creating an object oriented design in C is for every method you have you will pass in a reference to a struct which is used to store all the classes member variables. In otherwords in C++ where you'd have listObj.clear() you have in C list_clear(&listObj).
This is kind of ugly, but it's necessary unless you want to use static member variables and limit the implementation to being used only once.
In the example below, notice how in each method a reference to a struct ParamUtilObj is passed in.
// --- paramUtil.h
// Stores all the objects member variables (public and private)
struct ParamUtilObj {
int paramCnt;
char param1[25];
char param2[25];
...
};
bool paramUtil_initialize( struct* ParamUtilObj pData );
bool paramUtil_addParam( struct* ParamUtilObj pData, const char* pKey, const char* pValue );
bool paramUtil_execute( struct* ParamUtilObj pData);
With respect to variadic methods. I'd try to avoid them if possible and just add them in one at a time. The business logic to validate the params is an entirely different topic in my opinion. I'd need more info to recommend the best approach. But... It seems to me since you're going to have to do validation such as if( MethodA ) then check for presence of some other argument... it might be easier to create several SetParam methods for each MethodType which the user could specify in the script.
I would recommend using a linked list to store your params and put all your methods as function pointers to a struct.
struct MyClass {
struct LinkedList* params;
void (*setParams)(...);
void (*execute)()
}
the linked list would be a key value pair
struct LinkedList {
struct LinkedList *next;
char * key;
char * value;
}
I dont know how you have your SetParams implemented, from the sound it just does a little bit of parsing and storing and forwards error handling downstream to the Execute call.
Since you are using variable length arguments, are you using the va_* macros? Doing so with a format string might allow you to insert the error handling into your SetParams call and allow Execute to just iterate over the values and do its thing.
Generally, if you have a function that handles setting parameters that should be where you manage errors associated with setting parameters. Errors encountered in the execution of command should be addressed in the execute function.
You cannot do it this way, because in C variadic functions don't know the number of arguments you've supplied, so you need somehow let function know it, like specifying number of params as first parameter or use printf way, when number of parameters can be found from format string.