我编写了一个使用函数指针数组的C程序。该 函数都在我的程序内和可加载的DLL中。我的问题来了 当我尝试使用来自C ++程序的DLL时。这是一个简化的 C ++(DLL)程序中代码的snippit:
#ifdef __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif
typedef struct { float x,y,z; } VECT;
EXPORT VECT norm(OBJECT *obj, RAY ray, float t, VECT *pt, RGB *col)
{
VECT npt;
...
*pt = npt; /* give pt a new value */
...
}
问题是,一旦我尝试用pt做任何事情就崩溃了。不是 NULL,但如果我尝试写入它或者甚至只是访问它的成员,它 崩溃。我通过将C ++代码转换为C来解决问题,但是 我真的很想知道为什么会崩溃。如果我采取任何尝试 访问pt,该程序工作正常(除了缺少功能 会有一个正确的pt)。顺便说一句,这是另一个奇怪的事情 - 当我在现在的C DLL代码中执行以下操作时:
EXPORT VECT norm(OBJECT *obj, RAY ray, float t, VECT *pt, RGB *col)
它崩溃了。但如果我这样做:
EXPORT VECT norm(obj, ray, t, pt, col)
OBJECT *obj;
VECT *pt;
RAY ray;
float t;
RGB *col;
它没有崩溃。有没有办法让C ++接受第二种方式 指定参数?
额外信息,如有必要......我用以下代码加载DLL函数:
typedef struct Funcs
{
int (*inter)();
VECT (*normal)();
} FUNCS;
/*
I've also tried:
typedef VECT (WINAPI *FNORMAL)(OBJECT *obj, RAY ray, float t, VECT *pt, RGB *col);
(FNORMAL)GetProcAddress...
*/
funcs[i].normal = (VECT *)GetProcAddress(dll2, "norm");
if (funcs[i].normal == NULL) { printf("Error: No norm procedure in '%s'\n", objstr); quit(); }
并用:
打电话给他们hit.normal = funcs[p->type].normal(p, ray, mint, &pt, &colm);
我已经尝试完全指定了类型(而不仅仅是VECT *) GetProcAddress类型转换。
我甚至尝试在我的linux版本中执行此操作。它也会崩溃,所以事实并非如此 仅限Windows的问题。
有什么想法吗?
答案 0 :(得分:2)
对我来说,这个问题看起来源于这个宣言:
VECT (*normal)();
在这里,您告诉编译器normal
是指向返回VECT
的函数的指针。但是你还没有指定函数的参数,所以编译器会让你传递你喜欢的任何东西,它会尝试找出要传递的类型。这是非常糟糕的做法。你应该停止这样做。将法线声明更改为如下:
VECT (*normal)(OBJECT *obj, RAY ray, float t, VECT *pt, RGB *col);
我无法在C ++代码中看到指定调用约定的任何地方,因此假设cdecl
的默认值有效。显然你需要在界面上匹配它,如果你没有为你的函数指针指定调用约定,那么你也会得到默认的cdecl
。
答案 1 :(得分:0)
在DLL构建和客户端构建期间,您必须确保所有涉及的编译参数都是兼容的。需要特别注意:
如果所有这些看起来都很好,请在调用函数时断开,并显示作为参数传递的所有内容。然后进入函数并检查一切看起来是否相同。