怎么⽤c语⾔编写dll动态库,WPF调⽤dll-⽤C语⾔编写动态库概述
⽤C语⾔编写⼀套接⼝供C#调动,实现:
malloc⼀块内存内存,通过参数初始化内存,并返回cdll_t句柄
打印cdll_t内存中数据
freecdll_t内存
接⼝函数
这⾥我们⽤到了struct来管理开辟的内存
关于性别的枚举:
typedef struct
{
bool sports; /* whether be qualified or not */
uint8_t language;
uint16_t total;
uint8_t english;
uint8_t math;
} class_config_t;
关于课程的结构体:
typedef enum
{
GENDER_MALE,
FEMALE,
} gender_mode_t;
团队的结构体:
typedef struct
{
gender_mode_t gender_mode;
bool specific;
uint8_t headcount;
uint8_t class_config_count;
class_config_t class_config[CLASS_CONFIG_MAX_COUNT];
} team_config_t;
如果⽤类的思想来理解:
设计接⼝函数
PROXY_TEST_API cdll_t struct_create(team_config_t team_config);
PROXY_TEST_API int struct_output_log(cdll_t tc);
PROXY_TEST_API void struct_destroy(cdll_t tc);struct_create⽤于传⼊⼀个team_config_t的结构体,并malloc内存块TC
struct_output_log传⼊TC的指针,内部⽤log打印输出TC内的数据,并返回操作结果
struct_destroy传⼊TC的指针,并freeTC
接⼝编写注意点
DLL的export:c语言编译器怎么用?
DLL中包含有⼀个表,称为export table(以下简称ET),其中包含了DLL中可以被外部程式使⽤的所有函数和数据的名字。只有记录在ET中的函数和数据才可以被外部程式所使⽤(如果没有.DEF⽂件的话),其它所有没有记录在ET中的函数和数据都被视为是DLL私有的。因此,要将DLL中的函数和数据export只有两个⽅法:
为DLL创建⼀个.DEF⽂件(模块定义⽂件),并在build该DLL时使⽤这个.DEF⽂件。使⽤这种⽅法使你可以将函数按序号export。
在DLL中想要export的函数和数据定义前添加_declspec(dllexport)关键字(对于函数和变量定义,加在最前⾯;对于class定义,加在class关键字后),这样该函数和数据就会被添加到ET中。使⽤这种⽅法函数将按名字export。
在WINDOWS下,⽆论使⽤上述的哪⼀种⽅法,都必须要将export函数声明为_stdcall。
DLL的import:
外部程式的⼀个源⽂件要使⽤DLL中的函数和数据,就像要使⽤外部模块中的函数和数据⼀样,必须⾸先给出函数和数据的声明;对于class则要给出类的定义。这就称为import。对于VC编译器,Import DLL的函数和数据的语法与⼀般的声明类似,但要在前⾯加上
_declspec(dllimport)关键字(对于函数和变量声明,加在最前⾯;对于class定义,加在class关键字后)。如果是函数,则该关键字是可选的,但使⽤该关键字有可能会导致编译器产⽣较⾼效的代码。但对于变量和class,则必须使⽤该关键字。
通过使⽤以下的技术,可以编写在.LIB⽂件和外部程序源⽂件通⽤的头⽂件:
#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
编译器提供的_EXPORTING宏可以⽤于标式该源⽂件来⾃DLL⽂件还是外部程式。
关于C和C++的兼容问题:
如果要写C和C++兼容的DLL,因为在C和C++下使⽤了不同的名字修饰规则以及不同的调⽤约定,所以,如果DLL是⽤C编写和编译的,则在⽤于C++模块时,函数的声明前应加上extern “C”关键字,以告诉LINKER使⽤C外部连接(即按照C名字修饰规则在外部模块中寻函数);反之,如果DLL是⽤C++编写和编译的,则在⽤于C模块时,函数的声明前要加上extern “C++”关键字。VC++通过_cplusplus 宏来标识C++程式。如果是C++程式,VC编译器就会为你定义_cplusplus宏。所以在DLL中可以使⽤如下的技术来解决兼容问题:
#ifdef _cplusplus
extern “C” {
#endif
// 将所有的函数声明放在这⾥
#ifdef _cplusplus
}
#endif
.DEF⽂件:
.DEF⽂件是包含了DLL模块信息的⽂本⽂件。其语法结构如下:
LIBRARY DLL file name
DESCRIPTION “descriptions”
EXPORTS
Function names @nums
LIBRARY为关键字,后⾯紧跟关联的DLL⽂件名;DESCRIPTION后为可选的描述字符串,除了增加可读性外没什么⽤处;EXPORTS后是export函数的列表,⾸先是函数名,然后是@符号,后紧跟⼀⼗进制数,为该函数的标号,范围从1到DLL可export函数的总数。注意,这⾥的名字是经过名字修饰后的函数名字,如果是DLL是⽤C++写的话,那么就很郁闷了。
如果是扩展DLL(extension DLL),并且通过.DEF⽂件export,那么必须在头⽂件中添加如下的语句:
#undef AFX_DATA
#define AFX_DATA AFX_EXT_DATA
// 头⽂件中的其它内容
#undef AFX_DATA
#define AFX_DATA
这些语句确保⼀些MFC中内部使⽤的变量被export到外部程式中。例如:在class中通过DECLARE_DYNAMIC获得的CRuntimeClass变量。否则DLL将会⽆法正确地编译和连接,或外部程式⽆法正确连接到该DLL。
源码
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论