gpt4 book ai didi

c++ - 将函数指针作为 API 接口(interface)传递给已编译的库

转载 作者:太空宇宙 更新时间:2023-11-04 02:08:00 25 4
gpt4 key购买 nike

最亲爱的堆栈交换,

我正在为 MRI 扫描仪编程。我不会介绍太多背景知识,但我在访问多少代码方面相当受限,而且设置的方式是……次优的。我的情况如下:

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

简而言之,我的问题是:

  • 在一个方法的中间,在一个大 blob 中的数千行代码的一个深暗角落里,我几乎无法控制,天知道发生了什么变量作用域,我需要:
    • 扩展此方法以将函数指针(指向用户态函数)作为参数,但是
    • 让这个在编译库之后编写的用户空间函数可以访问它出现的方法范围内的局部变量,以及调用它的 (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 代码中,您正在调用“Something”函数(C++ 类/函数),函数指针指向“doUseFullThings”作为参数。现在控制转到 C++ 库。在这里,各种参数被分配内存并被初始化。然后使用这些参数调用“doUseFullThings”。此处控制权转移回 C 代码。简而言之,主程序(C)调用库(C++),库调用C函数。

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

malloc 语句返回指针。这没有得到妥善处理。(可能你试图给我们概述)。您必须注意在某个地方释放它。

由于这是 C 和 C++ 代码的混合,因此很难使用 RAII(处理分配的内存)、Perfect forwarding(避免复制变量)、Lambda 函数(访问局部变量)等。在这种情况下,您的方法似乎是可行的方法。

关于c++ - 将函数指针作为 API 接口(interface)传递给已编译的库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18613709/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com