我在静态库中有一个C函数,我们称它为A,具有以下接口:
int A(unsigned int a, unsigned long long b, unsigned int *y, unsigned char *z);
此函数将更改y和z的值(这是肯定的)。我在动态C ++库中使用它,使用extern“C”。
现在,这是让我感到困惑的事情:
我认为以上几点表明,我的变量声明并不是一个愚蠢的错误。
我明显卡住了,我无法更改C库。你有什么问题可以解决吗? 我正在考虑C / C ++接口上的一个问题,每个实例都是解释char *的方式。
编辑:我终于找到了问题所在。请参阅下面的答案。
答案 0 :(得分:4)
看起来你的C库和C ++编译器处理 long longs 的方式有所不同。我的猜测是,C库可能是C89之前的标准,实际上将64位 long long 视为32位长。您的C ++库正确处理它并在调用堆栈上放置64位,从而破坏了y和z。也许尝试通过* int A(unsigned int a,unsigned long b,unsigned int * y,unsigned char z)调用函数,看看你得到了什么。
只是一个想法。
答案 1 :(得分:2)
这是其中一个问题,即你所描述的内容并没有明显错误,但事情并没有按照你期望的方式发挥作用。
我认为您应编辑您的帖子以提供更多信息,以便获得一些明智的答案。特别是,让我们从: -
开始除非您总是修改Z指向的数据,否则唯一可能的原因是参数传递约定之间不兼容。 “漫长的”问题可能暗示事情并非像他们看似的那样。
作为最后的手段,您可以比较反汇编的C ++调用代码(您说失败)和C调用代码(您说成功),或者使用调试器逐步执行CPU指令(是的,真的 - 你'我将学习一项技巧并解决问题。
答案 2 :(得分:1)
据我所知,long long不是标准C ++的一部分,也许这就是你问题的根源。
答案 3 :(得分:1)
说不上。尝试调试 - 进入A并查看会发生什么(汇编代码警报!)
答案 4 :(得分:1)
也许你可以将原始函数包装在你从C ++库中调用的C库中?
根据您的第2点和第3点,看起来这可行。
如果没有,它会为您提供另一个调试点以查找更多线索 - 查看哪些库首先弹出故障,并检查为什么2和3工作,但这不是 - 最小的是什么差?
您也可以尝试检查函数调用在每种情况下设置的堆栈,以检查差异是否在这里 - 考虑不同的调用约定。
答案 5 :(得分:1)
步骤1:将从C ++端传递的指针y和z与C函数接收的指针进行比较。
P.S。我不想听起来很明显,但只是在这里仔细检查。我想当你说从C二进制文件中调用时z被修改得很好,你的意思是z指向的数据被修改得很好。指针y和z本身是按值传递的,因此您无法更改指针。
答案 6 :(得分:1)
另一个猜测:您确定要链接到C库中正确的函数实例吗?是不是你的图书馆里有几个这样的功能?在C中,链接器在决定如何解析函数时不关心返回类型或参数列表 - 只有名称很重要。所以,如果你有多个具有相同名称的函数......
您可以通过编程方式验证函数的身份。创建一个C库,使用一些测试参数调用您的函数A,并且工作正常,并将指针打印到函数A.将库链接到您的C ++应用程序。然后将指针打印到原始A函数,如C ++代码所示,并在同一进程中调用时将指针与C库看到的指针进行比较。
答案 7 :(得分:1)
同样,一个明显的,但谁知道......你确定你正在调用的C函数是无状态的,这意味着它的输出仅取决于它的输入吗?如果函数不是无状态的,则可能是“隐藏”状态负责从C ++应用程序调用时函数的不同行为(不更改z
指向的数据)。
答案 8 :(得分:1)
首先,我非常感谢大家的帮助。 感谢您给我的众多想法和线索,我终于能够解决这个问题。你的建议帮助我质疑我认为理所当然。
对我的问题的简短回答:问题是我的C ++库使用旧版本的C库。这个老版本错过了第四个论点。因此,第四个论点显然从未改变过。
我现在有点惭愧,因为我意识到这是问题所在。但是,由于我的代码编译得很好,我被误导了。这是因为C ++库是针对正确版本的C lib编译的,但在运行时它使用了与我正在使用的另一个库静态链接的旧版本。
C++ Lib (M) ---> dyn C++ lib (N) ---> C lib (P) v.1.0
|
------> C lib (P) v.1.1
(N)是一个动态库,它与(P)1.0版静态链接。 编译器接受了从(M)到具有4个参数的函数的调用,因为我链接了(P)版本1.1,但在运行时它使用旧版本的(P)。
随时编辑此答案或问题或要求我这样做。
答案 9 :(得分:0)
在你的C ++程序中,是用extern "C"
声明的原型吗?