access pointer to function in unmanaged code - c++

I am creating a CLR project to access my C code. It was going ok till one of the C function needed a callback. I'm not sure how to resolve this, have tried a couple of different things.
C:
typedef void(*logger_callback_t)(const char *, int);
Given the above in C, how can I assign this callback? I've tried creating a function and referencing it but getting errors. If I put the c++ function in the header it gives "pointer-to-member is not valid for a managed class". If I put it next to the function I get undeclared identifier
C++:
logger_callback_t logger = &dummy_logger_callback;
void dummy_logger_callback(const char *, int)
{
}

I'm not super clear on the issue but it seems like this is a declaration order problem. One option may be to forward declare the callback until the function is declared.
static logger_callback_t logger;
static void dummy_logger_callback(const char *, int)
{
}
logger = dummy_logger_callback;
This should work in a C context, but if your function is a method of a class or your variable is a member of a class this can get more complex. It is also complicated by what the intended storage class (static, extern etc) is for the variable and the function. Could you be more specific about the setup?

That callback should be a free function, not a member function. If you're declaring it inside a class, don't.
Valid code might look like:
// at file scope (not inside a class):
extern "C" {
void dummy_logger_callback(const char *, int)
{
// your code here
}
}
// ... and in your existing C++ code:
logger_callback_t logger = &dummy_logger_callback;

Related

Passing an instance method to an API that expects a C function pointer

I have a C API to a data source. To be notified that new data is available you give the API a callback in the form of a function pointer; your callback will be called when data comes in. The API’s header contains lines like this:
struct DataRecord { ... };
typedef void (*DataCallback)(DataRecord *data);
void set_data_callback(DataCallback processor);
My C++ class has an instance method with the signature
void MyClass::process_data(DataRecord *data);
and in the constructor of MyClass I’d like to set the new instance’s process_data method as the data callback for the C API. Following this answer I tried to write this code in the constructor:
typedef void (MyClass::data_callback_t)(DataRecord*);
data_callback_t callback = &MyClass::process_data;
set_data_callback(callback);
When I do this I get the error
error C2664: 'set_data_callback' : cannot convert parameter 2 from 'data_callback_t' to 'DataCallback'
There is no context in which this conversion is possible
(I am using Visual C++ 2010 Express, although I hope that doesn’t make a difference.)
How can I extract a C function pointer from an instance and a method?
You can't. MyClass::process_data can be thought of as a void(MyClass*, DataRecord*), which is the wrong type. You'd have to wrap your class pointer into the call somehow.
One approach might be to introduce a type with a static pointer:
struct MyClassCallbackHelper
{
static MyClass* myClass;
static void callback(DataRecord* record) {
myClass->process_data(record);
}
};
So that you can do:
MyClassCallbackHelper::myClass = this;
set_data_callback(&MyClassCallbackHelper::callback);

Using SQLite in C++: object function as a callback

So, I am working on a side-project to keep my c++ skills fresh (it has been many years since I have done work in c++). I am working on something where I will be using SQLite. I have a wrapper around the SQLite code. One of the things I am noticing is that SQLite uses c-style callback functions in its sqlite3_exec(...) function.
I would like to have the callback function be an object method, as I would like it to be able to modify object variables but am unsure of how to do this exactly. I have checked other similar questions on stackoverflow but came away with nothing helpful.
Here is how I am declaring my wrapper class:
class DBAdapter
{
private:
sqlite3* db;
int getUserRecords(std::string);
std::vector<USER_RECORD> records;
int callbackSel(void*, int , char**, char**);
public:
DBAdapter();
~DBAdapter();
int open(std::string);
void close();
int insertRecord();
int deleteRecord();
int getNumUserRecords();
};
Here is how I am trying to use the callback (callbackSel), from within getNumUserRecords:
int DBAdapter::getUserRecords(std::string name)
{
std::string sql = "SELECT" + name + " from USERS";
char* ErrMsg;
char* data;
int retval = sqlite3_exec(db,sql.c_str(),this->callbackSel,data,&ErrMsg);
return retval;
}
The error message I am getting is:
error: ‘int (* DBAdapter::callbackSel)(void*, int, char**, char**)’ is not a static member of ‘class DBAdapter’
My problem is, if I make this a static function, I won't be able to have access to my vector, records, right? Is there any way around this?
Is there any way around this?
I don't know for sqlite API specifically, but usually c-style callbacks support to have user data passed from a void* pointer (I'd guess the 1st parameter of that signature you mention). What one typically does is:
Declare a static class function to specify as callback function pointer
Implement that function to cast the passed user data pointer to a pointer to your class instance and call a member function
Have a member function defined in the class that provides the implementation you want
Pass a pointer to your handling class instance, when you're going to register the static member function pointer with the C API
I hope this points out the right direction.

C++: Warning (Anachronism) in Solaris Studio when creating a pthread from main using a static function within a class

I've been facing this warning.
I have a main C++ program which creates several threads. These threads run a function which is in a specific class. In order to do that, this class has a static function which returns the real function I am using to run in these threads. I'll paste the relevant parts of my code for you to understand it better.
These are the relevant parts of Car.h, the headers of the class whose function is run in the thread:
[...]
class Car {
public:
[...]
void *GoForward(void); //Runs in the thread
static void* GoForward_helper(void *); //Sends the previous one to the thread
[...]
This is the function in Car.cpp passed to pthread_create as argument, which returns the function which really runs in the thread. It is the only way I found to run in a thread a function of a different class:
[...]
void *Car::GoForward_helper(void *context) {
//Just getting parameters, not big deal
ThreadParameters* parameters = (ThreadParameters*) context;
int newSlot = parameters->GetSlot();
parameters->GetCar()->setSlot(newSlot);
//Returns the function I want to run in the thread
return parameters->GetCar()->GoForward();
}
[...]
void* Car::GoForward(void) {
//Tasks which actually run in the thread
}
[...]
These are the parameters sent to the helper function. Nothing relevant, I paste them for your convenience:
[...]
class ThreadParameters {
public:
ThreadParameters(Car*, int);
Car* GetCar();
int GetSlot();
[...]
private:
Car* context;
int slot;
[...]
...and finally this is the code in main() which creates the thread:
[...]
vector<Car *> cars; //Pointers to objects whose functions I want to run in threads
int threadsLaunched = 0;
pthread_t threads[numberOfThreads];
vector<int> freeSlots; //The number of threads is limited
[...]
int slot = freeSlots.at(0);
threadCode = pthread_create(&threads[slot], NULL,
&Car::GoForward_helper,
new ThreadParameters(cars.at(threadsLaunched), slot));
I am programming it in Solaris 10, using Oracle Solaris Studio 12.3. When building the project, I get this warning corresponding to the line in main() where I create the threads:
"main.cpp", line 80: Warning (Anachronism): Formal argument 3 of type
extern "C" void*()(void) in call to pthread_create(unsigned*, const
_pthread_attr*, extern "C" void*()(void), void*) is being passed void*()(void).
The code works like a charm, but I still get this warning when compiling and, honestly, I hate not having a fully clean compiling process. I have found dozens of solutions using extern "C", but none of these solutions match with the structure of my code, so none of them worked for me, and I would like to get rid of any warning (solving them, not hiding them).
You're getting the warning because pthread_create() expects a pointer to function with C language linkage, but you're passing it Car::GoForward_helper which has C++ language linkage. While in practice this will most likely work, these two are actually different; for example, C and C++ linkage functions could be using different calling conventions.
Unfortuantely, a class member (even a static one) cannot have language linkage other than C++. In other words, going strictly by the letter of the rules, it's impossible to use a static member function as a callback where a C function is expected.
To solve this, you must make the helper a free function and give it C language linkage:
[...]
class Car {
public:
[...]
void *GoForward(void); //Runs in the thread
[...]
};
extern "C" void* GoForward_helper(void *); //Sends GoForward() to the thread
Implemented like this:
extern "C" void *GoForward_helper(void *context) {
//Just getting parameters, not big deal
ThreadParameters* parameters = (ThreadParameters*) context;
int newSlot = parameters->GetSlot();
parameters->GetCar()->setSlot(newSlot);
//Returns the function I want to run in the thread
return parameters->GetCar()->GoForward();
}
An additional option, especially if the function needs member-like access, you could keep the static one and simply delegate to it:
[...]
class Car {
public:
[...]
void *GoForward(void); //Runs in the thread
static void* GoForward_helper(void *); //Sends the previous one to the thread
[...]
};
extern "C" void* GoForward_helper_C(void *);
Implemented like this:
extern "C" void* GoForward_helper_C(void *arg) {
return Car::GoForward_helper(arg);
}

Passing function pointer with scope resolution operator arduino

I'm a newbie to arduino and programming.
I've included a library inside my own library in arduino, but first library contains a function which has a pointer function as a parameter. It is an interrupt service routine(ISR) but I need to call a function in my cpp file when interrupt is occurred. So I need to pass the pointer of that function to the first library code. It works well when I use it in .ino file, I can pass it like,
attachInterrupt(functionISR_name);
but when I use it in .cpp file, I get errors. my function is like,
void velocity::functionISR_name(){
//some code
}
but how can I pass the pointer of this function to the first library function? I tried this way but got errors,
attachInterrupt(velocity::functionISR_name);
You cannot pass a method to a function which expects a function, unless you define it static.
write it static :
static void velocity::functionISR_name()
and
attachInterrupt(&velocity::functionISR_name);
Unfortunately the static method is not bound to a specific instance any more. You should use it only together with a singleton. On Arduino you should write the class like shown below in the code snipped:
class velocity
{
static velocity *pThisSingelton;
public:
velocity()
{
pThisSingelton=this;
}
static void functionISR_name()
{
pThisSingelton->CallWhatEverMethodYouNeeded();
// Do whatever needed.
}
// … Your methods
};
velocity *velocity::pThisSingelton;
velocity YourOneAndOnlyInstanceOfThisClass;
void setup()
{
attachInterrupt(&velocity::functionISR_name);
// …other stuff…
}
This looks ugly, but in my opinion it is totally okay with Arduino as the opportunities are very limited on such a system.
Thinking again over it, I would personal go for the approach Sorin mentioned in his answer above. That would be more like that:
class velocity
{
public:
velocity()
{
}
static void functionISR_name()
{
// Do whatever needed.
}
// … Your methods
};
velocity YourOneAndOnlyInstanceOfThisClass;
void functionISR_name_delegation()
{
YourOneAndOnlyInstanceOfThisClass.functionISR_name();
}
void setup()
{
attachInterrupt(functionISR_name_delegation);
// …other stuff…
}
It would also save you some bytes for the pointer you need in the first example.
As a site note: For the future, please post the exact code (for e.g. attachInterrupt needs more parameter) and copy&paste the error messages. Usually error are exact at a place you do not suspect. This question was an exception. Normally I and other would ask for better specification.
You pass a pointer to the function but the function is a class member. Likely the call will be invalid because the this pointer will be garbage(may compile fine but will throw strange errors at runtime).
You need to define a plain vanilla function, outside of any class, and use that.
If you don't have a very complex project you can get away with having a global pointer to the class instance you should use and just delegate the call in your new function.
If you want to do thing the right way you need some mechanism to get the instance pointer I talked about above. Usually this involves either a singleton or some factory pattern.
Example:
class Foo {
void method() {
x = 5;
}
int x;
}
Having a callback on method will crash because you have an invalid pointer for this so x=5 will write 5 somewhere randomly in memory.
What you need is somehting like:
static Foo* foo_instance; // Initialized somewhere else.
void method_delegator() {
foo_instance->method();
}
Now you can pass method_delegator to the function. It will work because you now also pass foo_instance for this pointer.

Function pointer to class member function problems

First of all I have to admit that my programming skills are pretty limited and I took over a (really small) existing C++ OOP project where I try to push my own stuff in. Unfortunately I'm experiencing a problem which goes beyond my knowledge and I hope to find some help here. I'm working with a third party library (which cannot be changed) for grabbing images from a camera and will use some placeholder names here.
The third party library has a function "ThirdPartyGrab" to start a continuous live grab and takes a pointer to a function which will be called every time a new frame arrives. So in a normal C application it goes like this:
ThirdPartyGrab (HookFunction);
"HookFunction" needs to be declared as:
long _stdcall HookFunction (long, long, void*);
or "BUF_HOOK_FUNCTION_PTR" which is declared as
typedef long (_stdcall *HOOK_FUNCTION_PTR) (long, long, void*);
Now I have a C++ application and a class "MyFrameGrabber" which should encapsulate everything I do. So I put in the hook function as a private member like this:
long _stdcall HookFunction (long, long, void*);
Also there is a public void function "StartGrab" in my class which should start the Grab. Inside I try to call:
ThirdPartyGrab (..., HookFunction, ...);
which (not surprisingly) fails. It says that the function call to MyFrameGrabber::HookFunction misses the argument list and I should try to use &MyFrameGrabber::HookFunction to create a pointer instead. However passing "&MyFrameGrabber::HookFunction" instead results in another error that this cannot be converted to BUF_HOOK_FUNCTION_PTR.
After reading through the C++ FAQ function pointers I think I understand the problem but can't make up a solution. I tried to make the hook function static but this also results in a conversion error. I also thought of putting the hook function outside of the class but I need to use class functions inside the hook function. Is there another way or do I need to change my whole concept?
EDIT 14.01.08:
I tested the singleton workaround since I cannot change the third party library and the void pointer is only for data that is used inside the hook function. Unfortunately it didn't worked out of the box like I hoped.... I don't know if the static function needs to be in a separate class so I put it in my "MyFrameGrabber" class:
static MyFrameGrabber& instance()
{
static MyFrameGrabber _instance;
return _instance;
}
long Hook(long, long, void*); // Implementation is in a separate cpp file
In my cpp file I have the call_hook function:
long MFTYPE call_hook(long x, MIL_ID y, void MPTYPE *z)
{
return MyFrameGrabber::instance().Hook(x,y,z);
}
void
MyFrameGrabber::grab ()
{
ThirdPartyGrab(..., call_hook, ...);
}
But this gives me an error in static MatroxFrameGrabber _instance; that no matching standard constructor is found. That's correct because my MyFrameGrabber constructor looks like this:
MyFrameGrabber (void* x,
const std::string &y, int z,
std::string &zz);
I tried to put in an empty constructor MyFrameGrabber(); but this results in a linker error. Should I pass empty parameters to the MyFrameGrabber constructor in the singleton? Or do I need to have a separate Hook Class and if yes how could I access MyFrameGrabber functions? Thanks in advance.
SECOND EDIT 15.01.08:
I applied the changes and it compiles and links now. Unfortunately I cannot test this at runtime yet because it's a DLL and I have no Debug Caller Exe yet and there are other problems during initialization etc. I will mark the post as answer because I'm sure this is the right way to do this.
Your private member method has an implicit this pointer as first argument. If you write that out, it's obvious that the function signatures do not match.
You need to write a static member function, which can be passed as the callback-function to the library. The last argument to the HookFunction, a void*, looks to me very much like a cookie, where one can pass ones own pointer in.
So, all in all, it should be something like this:
class MyClass {
long MyCallback(long, long) {
// implement your callback code here
}
static long __stdcall ThirdPartyGrabCallback(long a, long b, void* self) {
return reinterpret_cast<MyClass*>(self)->MyCallback(a, b);
}
public:
void StartGrab() {
ThirdPartyGrab(..., &MyClass::ThirdPartyGrabCallback, ..., this, ...);
}
};
This of course only works if the void* argument is doing what I said. The position of the this in the ThirdPartyGrab() call should be easy to find when having the complete function signature including the parameter names available.
The reason "&MyFrameGrabber::HookFunction" cannot be converted to a BUF_HOOK_FUNCTION_PTR is that, being a member of the class, it has implicitly as first parameter the "this" pointer, thus you cannot convert a member function to a non-member function: the two signatures look the same but are actually different.
I would declare an interface, defining the function to call, have your class implement it and pass the object itself instead of the callback (you can think of an interface as the object-oriented replacement of a function pointer):
class IHookInterface{
public:
virtual long HookFunction(long, long, void*) = 0;
};
class HookClass : public IHookInterface{
public:
virtual long Hook(long, long, void*) {
// your code here...
}
};
// new definition:
ThirdPartyGrab (..., IHookInterface, ...);
EDIT - other possible solution in case you cannot modify the library: use a singleton rather than a static function.
class HookClass{
public:
static HookClass& instance(){
static HookClass _instance;
return _instance;
}
long Hook(long, long, void*) {
// your code here...
}
};
long call_hook(long x,long y,void * z){
return HookClass::instance().Hook(x,y,z);
}
SECOND EDIT: you might slightly modify the singleton class with an initialization method to call the constructor with the proper parameters, but maybe it is not more elegant than the following solution, which is simpler:
class HookClass{
public:
HookClass(string x,string y...){
}
long Hook(long, long, void*) {
// your code here...
}
};
static HookClass * hook_instance = 0;
long call_hook(long x,long y,void * z){
if (0 != hook_instance){
return hook_instance->Hook(x,y,z);
}
}
int main(){
hook_instance = new HookClass("x","y");
ThirdPartyGrab(..., call_hook, ...);
}