GetProcAddress方法返回NULL值的问题

⌚Time: 2022-03-20 19:04:57

👨‍💻Author: Jack Ge

使用动态加载的方式使用动态库。

loadlibrary()成功加载动态库

之后使用GetProcAddress()方法得到函数指针却返回空值,使用GetLastError()方法得到错误代码127

出现此错误的原因一般是要加载的函数名称与动态库中函数名称不一致,要从库中加载的函数名为multiply

depends.exe查看动态库文件,函数名称是?multiply@@YAIXZ,这是使用c++编译后的函数修饰名

怀疑是动态库导出的函数符号名字问题

动态库头文件


#pragma once

__declspec(dllexport) int multiply(int);

class __declspec(dllexport) cABC{

private:

    char symbol;

public:

    cABC(char symbol);

    void print_l();

};

百度原因,使用extern “C”可以将导出函数名字固定。c与c++编译器不同。c++支持函数重载,实现方法是在编译阶段的函数被重命名变成函数名加参数名,类似?multiply@@YAIXZ这种代号,而c编译器就不会有这种机制了。加入extern “C”,能够实现c/c++混合编程。程序按照c编译器的方式编译链接。

不同编译器对于c++函数的符号命名是不同的,而使用c语言方式生成的符号是统一的,如果用extern “C”这种c语言符号的方式作为中转,也可以使不同编译器生成的库可以通用

extern的使用规则:


extern "C" void function();

extern "C" class className{

...

};

或者


extern "C"{

void function();

class className{

...

};

}

更好的写法是加入对c++的判断


#ifdef __cplusplus

extern "C" void function();

#else

void function();

#endif

或者


#ifdef __cplusplus

extern "C" {

#endif

void function();

#ifdef __cplusplus

}

#endif

按照此方法,修改头文件,重新编译一遍库。结果是GetProcAddress()成功返回函数地址


#pragma once

#ifdef __cplusplus

extern "C"{

#endif

__declspec(dllexport) int multiply(int);

class __declspec(dllexport) cABC{

private:

    char symbol;

public:

    cABC(char symbol);

    void print_l();

};

#ifdef __cplusplus

}

#endif

查看DLL文件,已经是c语言形式的函数修饰名

另外的情况,loadlibrary加载dll失败,如果GetLastError返回193,可能是dll位数和你的编译程序不一致,可能是64位程序调用了32位dll。这样也导致GetProcAddress无法获取到函数