当从C程序调用C ++ DLL时,它在我尝试访问DLL中的调用参数指针时崩溃

时间:2013-06-14 14:46:41

标签: c++ c dll parameters crash

我编写了一个使用函数指针数组的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的问题。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

对我来说,这个问题看起来源于这个宣言:

VECT (*normal)();

在这里,您告诉编译器normal是指向返回VECT的函数的指针。但是你还没有指定函数的参数,所以编译器会让你传递你喜欢的任何东西,它会尝试找出要传递的类型。这是非常糟糕的做法。你应该停止这样做。将法线声明更改为如下:

VECT (*normal)(OBJECT *obj, RAY ray, float t, VECT *pt, RGB *col);

我无法在C ++代码中看到指定调用约定的任何地方,因此假设cdecl的默认值有效。显然你需要在界面上匹配它,如果你没有为你的函数指针指定调用约定,那么你也会得到默认的cdecl

答案 1 :(得分:0)

在DLL构建和客户端构建期间,您必须确保所有涉及的编译参数都是兼容的。需要特别注意:

  • 函数调用约定
  • 结构包装
  • 结构内容

如果所有这些看起来都很好,请在调用函数时断开,并显示作为参数传递的所有内容。然后进入函数并检查一切看起来是否相同。