我有一个C#应用程序和一个C ++ DLL,都是x86。 Application是启动项目,DLL项目位于同一解决方案中,并作为项目引用。 C ++ DLL输出其PDB文件,其名称与应用程序的Debug文件夹中的DLL相同。
我有一个名为SomeFunction
的函数,我试图在C#中执行。当代码到达该行时,它就会停在那里。 C#应用程序的UI继续响应,但断点永远不会离开该行(以及Form_Load中的那个)。
如果我尝试将DLL设置为启动项目并告诉它执行C#应用程序,则C#将在该行崩溃:System.EntryPointNotFoundException:无法找到名为' SomeFunction'的入口点。在DLL' SomeDLL.dll'。
这是我试图打电话的功能声明:
[DllImport("SomeDLL.dll", EntryPoint = "SomeFunction", CallingConvention = CallingConvention.Cdecl)]
public static extern int SomeFunction(IntPtr hwnd);
这是来自C ++标题的函数声明:
#define MYDLL_API __declspec(dllexport)
MYDLL_API extern int SomeFunction(HWND hWnd);
这是我从C#中调用它的方式:
var someAnswer = SomeFunction(_hwnd);
更新:由于下面的讨论可能需要一些时间来阅读,因此简而言之,答案是:我错过了一个外部人员" C"。另外,为了调试DLL(这也是一个问题),项目需要支持来自C ++和C#的本机调试,这是一个很好的列表,我经历过,最后一切都很好!
答案 0 :(得分:1)
我怀疑它事先没有设置断点的问题是DLL是通过p-invoke按需加载的。如果VS并不认为DLL是依赖项,则可能不允许您事先设置断点。
您可以在c ++代码中添加DebugBreak。然后只需运行您的应用程序,不要调试它。然后,当它执行此语句时,您将获得及时调试警报,允许您跳转到c ++调试器。
或者,您可以将DLL作为启动项目,但更改调试设置以便启动外部进程 - 在这种情况下是您的应用程序.exe。
但是,这一次,您不需要DebugBreak(),只需要一个常规断点。
现在,在调试时,会加载DLL符号,从而允许断点起作用。
我在ActiveX / COM上经常使用这个技巧。
答案 1 :(得分:1)
SomeFunction
的代码以确保加载非托管.dll symbols
状态。您可以尝试在该窗口中的c ++ dll的上下文菜单中加载symbols
。(通常会发生.net加载不同(非预期)版本的非托管.dll)
现在我很确定问题是导出的函数名称被破坏了。 尝试定义这样的函数:
extern "C" MYDLL_API int PASCAL SomeFunction(HWND hWnd);
在C#中:
[DllImport("SomeDLL.dll")]
public static extern int SomeFunction(IntPtr hwnd);