Function 从C+;调用导出的delphi函数时发生应用程序崩溃+;

Function 从C+;调用导出的delphi函数时发生应用程序崩溃+;,function,delphi,call,Function,Delphi,Call,我在Delphi7中编译了一个.DLL,它导出一个函数。我试图从C++调用那个函数。p> 过程系统重新加载(lpMessage:PAnsiChar;dwIcon:byte;dwColor:byte); 变量 消息:红衣主教; 程序系统重新加载_Real(lpMessage:PAnsiChar);汇编程序; asm ... 结束; 开始 dwMessage:=$00415B30; ShowGameMessage_Real(lpMessage); 结束; 导出SystemReload名称“Syste

我在Delphi7中编译了一个.DLL,它导出一个函数。我试图从C++调用那个函数。p>
过程系统重新加载(lpMessage:PAnsiChar;dwIcon:byte;dwColor:byte);
变量
消息:红衣主教;
程序系统重新加载_Real(lpMessage:PAnsiChar);汇编程序;
asm
...
结束;
开始
dwMessage:=$00415B30;
ShowGameMessage_Real(lpMessage);
结束;
导出SystemReload名称“SystemReload”;
开始
结束。

然后我用C++代码调用函数:< /p>

int ShowGameMessage(字符*消息、字节图标、字节颜色)
{
int ret;
如果(存在(“SysReload.dll”))
{
HMODULE hLib=LoadLibrary(“SysReload.dll”);
如果(hLib)
{
typedef int(uu stdcall*SGMessage)(字符*,字节,字节);
SGMessage ShowGameMessage=(SGMessage)GetProcAddress(hLib,“系统重新加载”);
ret=(*ShowGameMessage)(消息、图标、颜色);
}else{FreeLibrary(hLib);}
免费图书馆(hLib);
}
返回ret;
}
< >当调用导出的Delphi函数时,C++代码崩溃。
如何在不使应用程序崩溃的情况下正确操作?

您没有在Delphi代码中指定调用约定。Delphi中的缺省调用约定是“代码>登记器< /C>”(在C++ C++ Builder中称为代码>您的C++代码使用的是C++代码,用于输入函数(C++中的默认调用约定通常是代码>混合调用约定是未定义的行为,可能会导致各种问题,包括崩溃。您需要在两种语言中指定相同的调用约定。在这种情况下,在Delphi代码中应该使用<代码> STDCALL> /COD>,以匹配您的C++代码中使用<代码>
过程系统重新加载(lpMessage:PAnsiChar;dwIcon:byte;dwColor:byte);stdcall;
此外,您的Delphi代码将导出的函数声明为
过程
,这意味着它没有返回值。但是C++代码声明导入的函数具有<代码> int < /Calth>返回类型。在Delphi代码中,你应该更改C++代码以使用<代码> Value<代码>来匹配<代码>程序> <代码>:

typedef void(u stdcall*SGMessage)(字符*,字节,字节);

同样,在一个不相关的注释中,如果代码< > LoopRealSub()/Cuth>失败,C++代码将调用“代码>自由代码()/<代码>两次。如果

LoadLibrary()
失败,则根本不应该调用
freebrary()
。如果
LoadLibrary()
成功,则仅调用一次。您应该将对
FreeLibrary()
的调用移动到
if(hLib)
块中:

void ShowGameMessage(字符*消息、字节图标、字节颜色)
{
HMODULE hLib=LoadLibrary(“SysReload.dll”);
如果(hLib)
{
typedef void(uu stdcall*SGMessage)(字符*,字节,字节);
SGMessage ShowGameMessage=(SGMessage)GetProcAddress(hLib,“系统重新加载”);
如果(显示游戏消息)
(*ShowGameMessage)(消息、图标、颜色);
免费图书馆(hLib);
}
}

您没有在Delphi代码中指定调用约定。Delphi中的缺省调用约定是“代码>登记器< /C>”(在C++ C++ Builder中称为代码>您的C++代码使用的是C++代码,用于输入函数(C++中的默认调用约定通常是代码>混合调用约定是未定义的行为,可能会导致各种问题,包括崩溃。您需要在两种语言中指定相同的调用约定。在这种情况下,在Delphi代码中应该使用<代码> STDCALL> /COD>,以匹配您的C++代码中使用<代码>
过程系统重新加载(lpMessage:PAnsiChar;dwIcon:byte;dwColor:byte);stdcall;
此外,您的Delphi代码将导出的函数声明为
过程
,这意味着它没有返回值。但是C++代码声明导入的函数具有<代码> int < /Calth>返回类型。在Delphi代码中,你应该更改C++代码以使用<代码> Value<代码>来匹配<代码>程序> <代码>:

typedef void(u stdcall*SGMessage)(字符*,字节,字节);

同样,在一个不相关的注释中,如果代码< > LoopRealSub()/Cuth>失败,C++代码将调用“代码>自由代码()/<代码>两次。如果

LoadLibrary()
失败,则根本不应该调用
freebrary()
。如果
LoadLibrary()
成功,则仅调用一次。您应该将对
FreeLibrary()
的调用移动到
if(hLib)
块中:

void ShowGameMessage(字符*消息、字节图标、字节颜色)
{
HMODULE hLib=LoadLibrary(“SysReload.dll”);
如果(hLib)
{
typedef void(uu stdcall*SGMessage)(字符*,字节,字节);
SGMessage ShowGameMessage=(SGMessage)GetProcAddress(hLib,“系统重新加载”);
如果(显示游戏消息)
(*ShowGameMessage)(消息、图标、颜色);
免费图书馆(hLib);
}
}

您的Delphi导出看起来不像
\uu stdcall

因此,如果您使用的是C++Builder,请将其声明为
\uu fastcall
,或者在DLL中声明为
stdcall
。由于是DLL导出,
stdcall
可能是更好的选择

如果不使用C++ Builder,但另一个C++,那么<代码> yFASTLASK 不是选项,因为,您的<代码> yFASTLASK >与Delphi的默认<代码>登记< <代码>调用约定不兼容。最好将DLL函数声明为

stdcall
(或
cdecl
,尽管对于DLL,
stdcall
更为常见)

FWIW,使用默认的
寄存器
调用DLL导出约定是不允许的,原因如上所述