您好我在Delphi 2007应用程序中集成DLL时遇到了一些问题。
我怀疑我对调用的参数做错了。 此刻我有2个问题,但我认为它们是彼此相关的。
1) 首先使用DLL调用: 来自.h文件:
extern "C" {
__declspec(dllexport) HRESULT Startup(char* version);
}
这个调用应该初始化DLL并给我DLL的版本。 HRESULT应为0,版本指针应包含版本。
我的Delphi代码:
function Startup(var version: Pchar): HRESULT; cdecl; stdcall; external 'myDLL.dll';
和实际的电话:
var
res : HRESULT;
Name1 : PChar;
test : AnsiString;
buf2: array [0..20] of AnsiChar;
begin
FillChar(buf2,20,0);
Name1:= @buf2[0];
res := RdmStartup(Name1);
//Here res = 0, but the Name1 stays empty, and the buf2 still contains 0.
end;
但结果是0,这个电话是成功的。
然后我的第二个问题:我需要调用DLL中的一个函数来打开一个COM端口。
.h:
extern "C" {
__declspec(dllexport) HRESULT Open(HWND hWnd, int Port, DWORD BaudRate, DWORD Interval);
}
我的德尔福宣布:
function Open(hWnd: HWND;Port : integer;BaudRate:LongInt;Interval:LongInt): HRESULT; cdecl; stdcall; external 'myDLL.dll';
我称之为:
res:= Open(self.Handle,5,115200,500);
这里我在res变量中从DLL中恢复失败。 我也有DLL的来源,我得到的失败来自DLL正在检查参数是否有效的部分,如果它们有效则会继续,否则返回我当前得到的错误。
正在检查的事情:
if(hWnd == NULL)
{
return false;
}
if(BaudRate != 2400 && BaudRate != 9600 && BaudRate != 38400 && BaudRate != 115200)
{
return false;
}
if(IntervalTimer < 300)
{
return false;
}
std::string strPortName = lexical_cast<std::string>( format("COM%d") % Port);
std::string strPortName(lpPortName.c_str());
std::string::size_type loci = strPortName.find("COM");
if( loci == std::string::npos )
{
return false;
}
return true;
以上其中一个在我的调用中返回false,因为如果此函数的结果为false,则DLL会给出我当前在结果中得到的错误。 有没有人知道我做错了什么?
我已尝试过多种类型的组合,最后我坚持转换,我发现:http://www.drbob42.com/delphi/headconv.htm 我也尝试了不同的方法来读取char指针,但所有这些都失败了.....
所以在这个阶段我知道我已经成功地与DLL通信,因为我为2次调用获得了不同的HRESULT,但我怀疑我的参数不像应该那样工作。
我正在使用Delphi 2007,而C ++ DLL是使用VS2010构建的。
答案 0 :(得分:1)
启动声明非常可疑:
__declspec(dllexport) HRESULT Startup(char* version);
这转化为:
function Startup(version: PAnsiChar): HResult; stdcall; external 'myDLL.dll';
所以那里应该没有var
。
我从您的评论中得出cdecl
调用约定适用于您的某些代码。在这种情况下,删除 stdcall
,因为它取代了前面的cdecl
。
Open()
的声明似乎相当不错(我会使用DWORD
作为类型,而不是Longint
,特别是因为DWORD
现在是Longword
- 但在Win32中,它们的大小相同,因此不会对你产生任何重大影响)。你似乎也传递了正确的参数。
你没有写下你回来的HRESULT
值。但我认为端口COM5
根本无法使用这些设置打开。
您应该从var
删除Startup()
。
所以你可以尝试:
cdecl
代替stdcall
(声明中的stdcall
取代cdecl
)HRESULT
。如果没有相同的硬件和软件,从远处进行更好的诊断是不可能的,抱歉。
你可以阅读我的article on conversion。这也有一些段落解释了如何调试代码以找出正确的调用约定。它也可以帮助您解决转换标题的更多问题。