现在的位置: 首页 > 综合 > 正文

c#调用C++的DLL找不到入口点

2013年02月23日 ⁄ 综合 ⁄ 共 2114字 ⁄ 字号 评论关闭

C++源码如下:

C++代码
复制代码

收藏代码
  1. —————————————————a.h————————————————— 
  2. #ifdef A_EXPORTS 
  3. #define A_API __declspec(dllexport) 
  4. #else 
  5. #define A_API __declspec(dllimport) 
  6. #endif 
  7.  
  8. A_API int F(void); 
  9. —————————————————a.cpp————————————————— 
  10.  
  11. #include "stdafx.h" 
  12. #include "a.h" 
  13. BOOL APIENTRY DllMain( HANDLE hModule, 
  14.                        DWORD  ul_reason_for_call, 
  15.                        LPVOID lpReserved 
  16. switch (ul_reason_for_call) 
  17. case DLL_PROCESS_ATTACH: 
  18. case DLL_THREAD_ATTACH: 
  19. case DLL_THREAD_DETACH: 
  20. case DLL_PROCESS_DETACH: 
  21. break
  22.     return TRUE; 
  23.  
  24. A_API int F(void
  25. MessageBox(NULL, "1212", "1212", MB_OK); 
  26. return 0; 

C#源码函数原型声明:

[DllImport("a.dll")]
public extern static int F();
调用后提示找不到入口点

在命令行用dumpbin /exports 看函数名:

dumpbin /exports a.dll
函数名不是"F"?而是"?F@@YAHXZ"

C#函数声明写成:

C#代码
复制代码

收藏代码
  1. [DllImport("a.dll",EntryPoint="?F@@YAHXZ")] 
  2. public extern
    static int F(); 

这样调用成功!

原因:在C++函数声明时要将 extern "C" 添加在 DLL 函数声明之前

主要注意包含 DllImport 的代码行。此代码行根据参数值通知编译器,使之声明位于 User32.dll 中的函数并将签名中出现的所有字符串(如参数或返回值)视为 Unicode 字符串。如果缺少 EntryPoint 参数,则默认值为函数名。另外,由于 CharSet 参数指定 Unicode,因此公共语言运行库将首先查找称为 MessageBoxW(有 W 是因为 Unicode 规范)的函数。如果运行库未找到此函数,它将根据调用约定查找 MessageBox 以及相应的修饰名。受支持的调用约定只有
__cdecl 和 __stdcall。
当调用用户定义的 DLL 中所包含的函数时,,如下所示:
// The function declaration in SampleDLL.h file
extern "C" SAMPLEDLL_API int fnSampleDLL(void);

Dumpbin.exe位于 VS的安装目录\VC\bin下,如果点击dumpbin.exe提示
出现mspdb80.dll无法找到的情况,是因为VC\Bin\下没有 “msobj80.dll,mspdb80.dll,mspdbcore.dll,mspdbsrv.exe”这四个文件(在VS2005中并没有这四个文件),解决的方法:
1>直接从Common7\IDE\下复制这四个文件到VC\Bin\下即可解决
2>添加系统变量 (Path),这样:我的电脑->属性->高级->环境变量->系统变量,在path中添加C:\Program Files\Microsoft Visual Studio 8\Common7\IDE;,注意结尾最后用“;”隔开!
这样在用ml编译就不会出现mspdb80.dll文件找不到的错误了

抱歉!评论已关闭.