今天写了一个exe链接dll的测试程序,隐式链接的时候没有问题,显式链接的时候获取的函数指针为空。之所以会出现这个问题,是因为在导出接口的时候没有加extern "C"导致的。由于c++中有函数重载,c语言中没有这个概念。 如果C++程序要调用已经被编译后的C 函数就需要在函数前加extern “C”。因为c语言中没有函数重载的概念,所以extern “C” 声明的函数无法重载
在C++中使用extern "C"会告诉C++编译器在编译时按照C语言进行编译,不进行换名,方便C语言去调用。那么这个换名该怎么理解呢?这里就涉及到了C++语法中函数重载的概念。
C++函数重载的实现原理:C++编译器是通过对函数进行换名,将参数表的类型信息整合到新的函数名中,解决函数重载何名字冲突的矛盾。例如下面两个函数:
void draw(int x, int y, int r);
void draw(int x, int y, int w, int h);
可以看到,函数名是相同的,但是参数列表是不同的,即所谓的“同名不同参”。C++编译器为了解决函数名称相同的冲突,在编译的时候会对函数进行换名以区分两个函数,然后再将参数表的类型信息整合到新的函数名中。
调用重载关系的函数,编译器会根据实参和形参的匹配程度,自动选择最优的匹配版本。g++编译器一般的匹配规则是:
完全匹配 >= 常量转换 > 升级转换 > 降级转换 / 过分升级转换 > …
升级转换示例:单字节 --> 四字节 浪费内存,但是可以保证数据完整性,数据安全性更好
降级转换示例:shor --> char 有风险,会损失值域
常量转换示例:char --> const char 更好