[转]关于C与C++中互相调用动态链接库的问题_卓越李子_新浪博客

[]关于CC++中互相调用动态链接库的问题

(2012-02-22 16:15:52)

转载

标签:

杂谈

分类: 工作窝

问题:

1.写一段C++程序,编译成动态链接库后,C程序怎么访问?

写一段C程序,编译成动态链接库后,C++程序怎么访问?

2.写一个类,编译成动态链接库后,里面的public变量能否访问?

对于以上问题,我在Visual C++ 6.0上进行了实验。以下是实验的过程和初步结论。

1. 建立动态链接库是在新建工程中选择Win32Dynamic-Link Library,建立空的工程,在里面添加头文件和实现文件(C程序用.c后缀,C++程序用.cpp后缀),以下给出C程序写的动态链接库代码和C++写的动态链接库代码(只包含一个Add函数):

Case1C程序的动态链接库代码:

 

//CLib.h

#ifndefC_LIB_H

#defineC_LIB_H

extern int__declspec(dllexport) add(int x,int y);

#endif

 

//CLib.c

#include"Clib.h"

int add( intx, int y )

{

return x +y;

}

 

Case2C++程序的动态链接库代码:

//CplusplusLib.h

#ifndefLIB_H

#defineLIB_H

extern"C" int __declspec(dllexport) add(int x, int y);

#endif

 

//CplusplusLib.cpp

#include"CplusplusLib.h"

int add( intx, int y )

{

return x +y;

}

 

由此可发现,其代码唯一不同的地方在于extern int __declspec(dllexport) add(int x,inty) 这一导出语句,在C程序中没有”C” ,而在C++程序多了一个标识”C

发生这个区别的原因是由于C++编译器与C编译器在对程序进行编译的时候,对函数声明的编译会有区别,加上”C”,是为了告诉C++编译器,使用C编译器的方式对这一个函数声明进行编译。这样,在C程序调用C++写的动态链接库的时候,才不会发生因为寻找不到对应的函数名(编译后的)而发生Link错误。

 

再来看调用,调用方式有两种:静态和动态。这的确是印证了老师说的万事皆有两面的道理。

使用动态的方式调用,不管在C还是在C++中,代码都是一样的,下面给出一个例子:

 

typedefint(*lpAddFun)(int, int);

 

int main(intargc, char* argv[])

{

       HINSTANCEhDll;

       lpAddFunaddFun;

       hDll= LoadLibrary("..//..//Debug//CplusplusDLL.dll");

       if(hDll != NULL)

       {

       addFun= (lpAddFun)GetProcAddress(hDll, "add");

       if(addFun != NULL)

       {

              intresult = addFun(2, 3);

              printf("%d",result);

       }

       FreeLibrary(hDll);

       }

       return0;

}

思路是定义一个函数指针,在主程序中使用LoadLibrary这个库函数载入DLL,然后再用GetProcAddress这个库函数获得DLL中函数所在的位置。调用完函数后使用FreeLibrary这个库函数释放DLL资源。

 

然而在静态的方式中,CC++的调用就略有不同,下面给出C++调用C库的程序:

 

//CplusplusApplicationStaticInvoke.cpp : Defines the entry point for the consoleapplication.

#include"stdafx.h"

#pragmacomment(lib,"CDLL.lib")

extern"C" __declspec(dllimport) add(int x,int y);

int main(intargc, char* argv[])

{

       intresult = add(2,3);

       printf("%d",result);

       return0;

}

#pragmacomment(lib,"CDLL.lib")这一句是表示在链接的时候将CDLL.dll这个动态链接库链接到这个程序当中。

 

而在C调用C++库的例子中:

//CApplicationStaticInvoke.cpp : Defines the entry point for the consoleapplication.

#include"stdafx.h"

#pragmacomment(lib,"CplusplusDLL.lib")

extern__declspec(dllimport) add(int x,int y);

int main(intargc, char* argv[])

{

       intresult = add(2,3);

       printf("%d",result);

       return0;

}

明显看到extern __declspec(dllimport) add(int x,int y); 与上一例子不同,少了一个”C

 

这个原因很明显,就是为了动态库中的函数名进行对应。在CDLL中函数当然是使用C编译器的方式进行编译的,所以在调用程序中,在声明外部函数的时候,必须加上”C”,以使的这个C++程序,在编译的时候使用C编译的方法对这个外部函数声明进行编译,否则在编译运行的时候就会报链接错误。在C++调用C的例子中我们将”C”去掉,结果:

LNK2001:unresolved external symbol "__declspec(dllimport) int __cdecladd(int,int)" (__imp_?add@@YAHHH@Z)

上面add@@YAHHH@Z就是add函数用C++的编译方法编译后的得到的函数名,而C编译得到的应该是_add,链接的时候匹配不成功,因此就报错了。

 

2. 关于类的public变量能够被访问,能否被直接访问,这里我仍没有找出答案,等待老师解答,但是有一个间接的方法能访问到类里面的变量。就是使用类的全局变量,将其导出即可,例子如下:

 

#ifdefCLASSDLL_EXPORTS

#defineCLASSDLL_API __declspec(dllexport)

#else

#defineCLASSDLL_API __declspec(dllimport)

#endif

 

classCLASSDLL_API CClassDLL {

public:

       CClassDLL(void);

       //Addedpublic member

       inttestNumber;

       //TODO: add your methods here.

};

 

externCLASSDLL_API int nClassDLL;

CLASSDLL_APIint fnClassDLL(void);

 

上面的标准宏是为了对导入导出进行匹配,这里先略过。

注意extern CLASSDLL_API int nClassDLL; 这句代码定义了这个DLL中的一个全局变量。注意这个时候宏CLASSDLL_API应该是__declspec(dllexport)表示导出该变量。

 

在调用的时候:

#pragmacomment(lib,"ClassDLL.lib")

extern int_declspec(dllimport) nClassDLL;

int main()

{

}

这样就可以直接在程序中访问nClassDLL了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值