Visual C++ DLL项目使用cpprestsdk时出现动态链接库入口点无法定位问题
兄弟,我之前在VC++里搞DLL加cpprestsdk(Casablanca)的时候,也碰到过一模一样的“无法定位入口点”坑,踩了好几个小时才爬出来。结合踩坑经验,这几个方向肯定能帮你解决问题:
1. 先把导出符号的写法改规范
你现在直接在静态方法上写__declspec(dllexport),虽然能导出,但很容易因为编译场景(是编译DLL还是调用DLL)搞混符号。最好用宏来区分:
在你的RestWrapper.h里改成这样:
#pragma once // 用宏区分导出/导入 #ifdef MYCPPREST_EXPORTS #define MYCPPREST_API __declspec(dllexport) #else #define MYCPPREST_API __declspec(dllimport) #endif namespace mycpprest { class RestWrapper { public: static MYCPPREST_API void TestApi(); }; }
然后去你的DLL项目属性里,找到C/C++ -> 预处理器 -> 预处理器定义,添加MYCPPREST_EXPORTS这个宏。这样编译DLL时自动导出符号,调用DLL的项目会自动导入,不会乱。
另外,你可以用VC自带的dumpbin /exports YourDll.dll命令(在VS的开发者命令提示符里运行),看看TestApi是不是在导出列表里。如果不在,说明导出写法有问题,比如漏加宏或者命名空间的影响(静态方法带命名空间的话,导出符号会是类似?TestApi@RestWrapper@mycpprest@@SAXXZ的格式,这是正常的)。
2. 必须匹配cpprestsdk的链接方式(静态/动态)
这是最容易踩的坑!cpprestsdk分静态和动态两种编译版本,必须和你的DLL项目的CRT链接方式完全匹配:
- 如果你的DLL用的是动态CRT(项目属性->C/C++->代码生成->运行库:
多线程DLL (/MD)或多线程调试DLL (/MDd)),那你必须用动态版本的cpprestsdk,链接cpprest_2_10.lib(Release)或cpprestd_2_10.lib(Debug)。 - 如果你的DLL用的是静态CRT(
/MT或/MTd),那必须用静态版本的cpprestsdk,链接cpprestsdk_2_10.lib(Release)或cpprestsd_2_10.lib(Debug)。 - 还要注意x86/x64、Debug/Release的配置完全一致,比如你DLL是x64 Debug,就不能用x86 Release的cpprest库,否则肯定会出现入口点找不到的问题。
3. 检查cpprestsdk的依赖DLL是否部署到位
如果你用的是动态版本的cpprestsdk,那你的DLL依赖的cpprestsdk的DLL(比如cpprest_2_10.dll)必须和你的DLL在同一个目录,或者在系统PATH里。如果缺失这个DLL,系统会找不到cpprest的符号,也会弹出“无法定位入口点”的错误。
调试的时候,直接把cpprest的DLL复制到你的DLL输出目录就行;发布的时候要记得一起打包这些依赖文件。
4. 确认cpprestsdk的库已经正确链接
你的RestWrapper.cpp里用到了cpprest的代码,那必须确保DLL项目已经链接了cpprest的库:
去项目属性的链接器->输入->附加依赖项里,添加对应的cpprest库文件(比如Debug下加cpprestd_2_10.lib),还要把cpprestsdk的库路径加到链接器->常规->附加库目录里。
最后给你个完整的RestWrapper.cpp示例,确保cpprest的代码能正常运行:
#include "stdafx.h" #include "RestWrapper.h" #include <cpprest/http_client.h> #include <cpprest/json.h> using namespace utility; using namespace web; using namespace web::http; using namespace web::http::client; using namespace web::json; namespace mycpprest { void RestWrapper::TestApi() { // 简单的示例请求,验证cpprest是否正常工作 http_client client(U("https://jsonplaceholder.typicode.com/")); client.request(methods::GET, U("todos/1")) .then([](http_response response) { if (response.status_code() == status_codes::OK) { return response.extract_json(); } return pplx::task<value>([] { return value(); }); }) .wait(); } }
内容的提问来源于stack exchange,提问作者noyruto88




