C++ 将函数指针作为API接口传递给编译库

C++ 将函数指针作为API接口传递给编译库,c++,c,function-pointers,library-design,C++,C,Function Pointers,Library Design,最亲爱的堆栈交换 我正在为核磁共振扫描仪编程。我不会深入到太多的背景中,但我在访问多少代码方面受到了相当大的限制,而且设置的方式……不太理想。我的情况如下: 有一个大的图书馆,用C++编写。它最终完成了“转码”(以最糟糕的方式),写出了完成任务的FPGA组件。它为“userland”提供了一组函数,这些函数被翻译成(通过预处理器宏和黑魔法的混合)16位和32位单词的长字符串。这样做的方式很容易导致缓冲区溢出,并且通常会导致溢出* 然后,FPGA组件通过美化的串行链路连接到相关的电子设备,由电子

最亲爱的堆栈交换

我正在为核磁共振扫描仪编程。我不会深入到太多的背景中,但我在访问多少代码方面受到了相当大的限制,而且设置的方式……不太理想。我的情况如下:

    有一个大的图书馆,用C++编写。它最终完成了“转码”(以最糟糕的方式),写出了完成任务的FPGA组件。它为“userland”提供了一组函数,这些函数被翻译成(通过预处理器宏和黑魔法的混合)16位和32位单词的长字符串。这样做的方式很容易导致缓冲区溢出,并且通常会导致溢出*
  • 然后,FPGA组件通过美化的串行链路连接到相关的电子设备,由电子设备执行(执行扫描),并再次返回数据进行处理
  • 程序员应该使用库提供的函数来完成他们的工作,使用与标准库链接的C(而不是C++)函数。不幸的是,在我的例子中,我需要扩展库
  • 在代码中编写doSomething()和相关库函数实际执行它之间,有一个相当复杂的预处理器替换和标记化、调用以及(通常)一些事情的链条。我想我在某种程度上已经弄明白了,但这基本上意味着我对任何事情的范围都没有真正的了解
简言之,我的问题是:

  • 在一个方法的中间,在一个大blob中数千行代码的一个黑暗角落里,我几乎无法控制,天知道发生了什么样的变量作用域,我需要:
    • 扩展此方法以将函数指针(指向userland函数)作为参数,但
    • 让这个在编译库之后编写的userland函数能够访问它出现的方法范围的局部变量,以及调用它的(C)函数中的变量
这似乎是内存管理的一个绝对的泥潭,我想在这里询问一下在这些情况下的“最佳实践”,因为我可能会遇到很多微妙的问题,而其他人可能有很多相关的智慧可以传授。调试系统是一场噩梦,我还没有得到扫描仪制造商在这方面的任何支持

我计划如何进行的简要概述如下:

在.cpp库中:

/* In something::something() /*
/* declare a pointer to a function */
    void (*fp)(int*, int, int, ...);
/* by default, the pointer points to a placeholder at compile time*/
    fp = &doNothing(...);

...

/* At the appropriate time, point the pointer to the userland function, whose address is supplied as an argument to something(): /*
    fp= userFuncPtr;
/* Declare memory for the user function to plonk data into */ 
    i_arr_coefficients = (int) malloc(SOMETHING_SENSIBLE);
/* Create a pointer to that array for the userland function */ 
    i_ptr_array=&i_arr_coefficients[0];
/* define a struct of pointers to local variables for the userland function to use*/
 ptrStrct=createPtrStruct(); 

/* Call the user's function: */
fp(i_ptr_array,ptrStrct, ...);

CarryOnWithSomethingElse();
占位符函数的要点是,如果用户函数未链接,则保持事情顺利进行。我知道这可以用
#DEFINE
来代替,但编译器的聪明或愚蠢可能会导致奇怪的行为(至少在我无知的头脑中是这样)

在userland函数中,我们有如下内容:

void doUsefulThings(i_ptr_array, ptrStrct, localVariableAddresses, ...) { 
    double a=*ptrStrct.a;
    double b=*ptrStrct.b;
    double c=*localVariableAddresses.c;
    double d=doMaths(a, b, c);
    /* I.e. do maths using all of these numbers we've got from the different sources */

    storeData(i_ptr_array, d);
    /* And put the results of that maths where the C++ method can see it */
}

...

something(&doUsefulThings(i_ptr_array, ptrStrct, localVariableAddresses, ...), ...); 

...
如果这像泥一样清澈,请告诉我!非常感谢你的帮助。顺便说一句,我真诚地希望有人能制作一个开放硬件/源代码的MRI系统


*顺便说一句,这是制造商用来阻止我们首先修改大型库的主要理由

您可以完全访问C代码。您对C++库代码的访问权限有限。C代码定义了“doUsefullthings”函数。从C代码中,您调用了“函数”函数(C++类/函数),函数指针指向“DouthFulthOutlook”作为参数。现在控件进入C++库。在这里,各种参数被分配内存并初始化。然后用这些参数调用“doUseFullThings”。在这里,控制权转移回C代码。简而言之,主程序(C)调用库(C++),库调用C函数

其中一个要求是“userland函数应该能够从调用它的C代码访问局部变量”。当你叫“某物”时,你只给出了“doUseFullThings”的地址。“something”没有捕获局部变量地址的参数/参数。所以“doUseFullThings”无法访问这些变量

malloc语句返回指针。这件事处理得不好。(可能你是想给我们概述一下)。你一定要小心把它放在什么地方


<>因为这是C和C++代码的混合,所以在使用这种情况下,很难使用RAII(照顾分配的内存)、完美转发(避免复制变量)、lambda函数(访问本地变量)等。您的方法似乎是正确的。

您是否正在执行函数指针,指向采用变量参数列表的函数?您在声明'fp'时使用了该语法,因此不清楚。我猜你只是用“…”来省略无用的细节?你是对的--我只是用“…”来省略细节,而不是实际包含变量参数列表。我现在意识到这是无济于事的。道歉!这是一个很好的概述——谢谢。首先;关于malloc()你是对的;第二,听到你认为没有比指针式乒乓球更好的方法,我感到相当欣慰。