现在的位置: 首页 > 综合 > 正文

C/C++调用Delphi制作的dll时发现的一些问题

2014年02月11日 ⁄ 综合 ⁄ 共 2851字 ⁄ 字号 评论关闭

做了一个网络业务逻辑实体,是用C++编写的dll,内部有一个全局的业务实体,外部准备用Delphi编写的界面程序来控制并显示状态......

 

1. C++dll中不能用C++风格的导出方式:_declspec(dllexport)来导出函数,要用C风格的导出方式:extern "C" _declspec(dllexport),否则Delphi在加载C++dll时报错:无法定位函数xxxFun()xxxDll.dll上。(这里假设只讨论这两种导出方式)不知道delphi能不能调用其他C风格的dll...?

例子:

C++中要这样声明函数,

extern "C" _declspec(dllexport) int Initialize();

Delphi中声明要这样,

Function Initialize():Integer; cdecl; external 'c_test.dll' name 'Initialize';

 

注意,这里的 cdecl 是必须的,其他的(如stdcallpascal...)貌似都不行......似乎它是delphi调用c编写的dll的唯一合法标识,因为这由C++dll中的_declspec方式决定了,然而在C++中为了能给delphi调用,又不允许使用其他的(如WINAPI,CALLBACKPASCAL...)导出方式,所以就只能这样使用_declspec了。

 

但是,有人说过这样的对应方式:

C++的参数调用方式           对应的DELPHI的参数调用方式

    _declspec                            cdecl

WINAPI,CALLBACK                  stdcall

      PASCAL                             pascal

附注:C++中的char *对应PASCAL中的PChar

不是没有试过,只是没有调试成功过,所以最终还是用的以上方式,即在C++中用extern "C" _declspec(dllexport)声明函数,在Delphi中用cdecl声明函数,然后Delphi应用程序调用C++dll

 

2.1中的调用为主动调用,即delphi主动调用C++dll,倘若反过来,用C++或者C来调用Delphi的函数,问题有些不一致了,这里又要分为两种情形:

1C++的应用程序,调用Delphi编写的dll

2Delphi在调用C++dll时,传递函数指针给dll,在dll内部根据业务逻辑,回叫这个delphi函数。

(其实1)和2)的情形似乎都一样...

因为pascalc是两种不同风格的语言,它们的参数列表的出栈进栈方式不一样,所以,最容易出问题的就是函数的参数列表了。不光参数列表中参数顺序会乱,而且乱得没有规律可循,当只涉及到一个整型参数时,没有问题,正常调用,但是,这只是碰巧没有问题而已......

首先,对于C++应用程序调用Delphi编写的dll

可以这样,在C++程序里,

#include <Windows.h>

#include <iostream>

#include <stdio.h>

#include <string>

using namespace std;

 

typedef int(*myFun)(int arg1,int arg2,int arg3,int arg4);

 

int main(int argi,char* argv[])

{

HINSTANCE hDll;

 hDll=LoadLibrary("delphi_dll.dll");

 if (hDll!=NULL)

 {

myFun fun;

 fun=(myFun)GetProcAddress(hDll, "c_exe_test2");

 if(fun!=NULL)

 {

       for(int i=0;i<5;i++)

{

              printf("%d,%d,%d,%d/n",i,i+1,i+2,i+3);

fun(i,i+1,i+2,i+3);

}

 }

 FreeLibrary(hDll);

}

 

system("pause");

return 0;

}

 

然后在Delphi编写的dl内部,

library delphi_dll;

 

uses

  SysUtils,

  Classes,

  Dialogs;

 

Function c_exe_test2(arg1,arg2,arg3,arg4: Integer): Integer; cdecl;

Begin

  ShowMessage(

'arg1='+IntToStr(arg1)+'    '+

'arg2='+IntToStr(arg2)+'    '+

'arg3='+IntToStr(arg3)+'    '+

'arg4='+IntToStr(arg4));

end;

 

exports

c_exe_test2 index 1;

 

begin

  //todo...dll被加载时执行一次...

end.

注意了,在Delphidll内部,cdecl 声明是必不可少的,否则就会出现参数列表的混乱...

 

接下来,就去调试下C++dll内部回叫Delphi程序的函数指针,再次检查参数列表是否正确,

C++dll中,

//--------------------------------------------------------------------------------

//xxx.h

typedef int(*OnTest)(int arg1,int arg2,int arg3,int arg4);

extern "C" _declspec(dllexport) int setcb_on_test(OnTest pFun);

 

//--------------------------------------------------------------------------------

//xxx.cpp

#include <Windows.h>

 

static OnTest CallBackOnTest = NULL;

extern "C" _declspec(dllexport) int setcb_on_test(OnTest pFun)

{

 CallBackOnTest=pFun;

       return 0;

}

 

void fun(void* arg)

{

       int i=0,arg1=1,arg2=2,arg3=3,arg4=4;

       while(1)

{

              i++;

              if(i%5==0)

if(CallBackOnTest)

{

              CallBackOnTest(arg1,arg2,arg3,arg4);

       arg1++;arg2++;arg3++;arg4++

}

              Sleep(1000);

              if(i>=100) break;

-->

作者:

抱歉!评论已关闭.