如何在32位C项目中调用64位C#项目的方法?
可行的实现方案
方案一:COM互操作(推荐跨位数场景)
32位和64位进程无法直接加载对方的DLL,COM通过跨进程调用机制可以解决这个位数不匹配问题。
- 配置C#项目
- 将C#项目设为类库,在项目属性的“生成”标签页勾选“使程序集COM可见”
- 给需要暴露给C的类和方法加上
[ComVisible(true)]属性:[ComVisible(true)] public class CsMethods { public string GetCSharpMessage() { return "这是来自C#方法的返回值"; } } - 生成项目后,用64位版本的
regasm.exe注册COM组件(路径通常是C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe):regasm.exe YourCSharpLibrary.dll /codebase
- 在32位C项目中调用
- 通过
CoCreateInstance创建C# COM对象,调用对应方法。示例代码:#include <windows.h> #include <stdio.h> int main() { HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr)) { CLSID clsid; // 替换成你的C#类的ProgID,格式是「命名空间.类名」 hr = CLSIDFromProgID(L"YourNamespace.CsMethods", &clsid); if (SUCCEEDED(hr)) { IDispatch* pDispatch = NULL; // 用CLSCTX_LOCAL_SERVER指定跨进程调用 hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pDispatch); if (SUCCEEDED(hr)) { // 这里省略了DISPID查找和方法调用的细节,实际需要按照COM调用规范处理参数与返回值 printf("成功调用C# COM组件\n"); pDispatch->Release(); } } CoUninitialize(); } return 0; } - 编译32位C项目,直接运行即可跨进程调用64位C#组件。
- 通过
方案二:中间代理进程
自己实现一个64位的代理程序,让32位C项目和代理进程通信,代理进程再调用64位C#类库。通信方式可选命名管道、TCP套接字或共享内存,这里以命名管道为例:
- 编写64位代理程序(C#控制台程序)
using System.IO.Pipes; using System.Text; class CSharpProxy { static void Main() { using (var pipeServer = new NamedPipeServerStream("CSharpCallProxy", PipeDirection.InOut)) { pipeServer.WaitForConnection(); byte[] buffer = new byte[256]; int readLen = pipeServer.Read(buffer, 0, buffer.Length); string request = Encoding.ASCII.GetString(buffer, 0, readLen); // 调用目标C#项目的方法 var result = new YourNamespace.CsMethods().GetCSharpMessage(); byte[] response = Encoding.ASCII.GetBytes(result); pipeServer.Write(response, 0, response.Length); } } } - 32位C项目中与代理进程通信
#include <windows.h> #include <stdio.h> int main() { HANDLE pipeHandle = CreateFile( L"\\\\.\\pipe\\CSharpCallProxy", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (pipeHandle != INVALID_HANDLE_VALUE) { char callCmd[] = "InvokeCSharpMethod"; DWORD bytesWritten; WriteFile(pipeHandle, callCmd, sizeof(callCmd), &bytesWritten, NULL); char response[256]; DWORD bytesRead; ReadFile(pipeHandle, response, sizeof(response), &bytesRead, NULL); printf("C#方法返回:%s\n", response); CloseHandle(pipeHandle); } return 0; } - 运行流程:先启动64位代理程序,再启动32位C程序,即可完成跨位数调用。
方案三:统一进程位数(如果业务允许)
如果可以把C项目改为64位编译,那么可以直接用UnmanagedExports NuGet包替代你之前尝试的dllExport,步骤如下:
- 给C#类库安装
UnmanagedExportsNuGet包 - 给要暴露的方法添加
[DllExport]属性:public class CsMethods { [DllExport] public static string GetCSharpMessage() { return "来自C#的直接调用结果"; } } - 编译64位C#类库,在64位C项目中导入调用:
#include <windows.h> #include <stdio.h> typedef const char* (*GetMessageFunc)(); int main() { HMODULE csDll = LoadLibraryA("YourCSharpLibrary.dll"); if (csDll != NULL) { GetMessageFunc getMsg = (GetMessageFunc)GetProcAddress(csDll, "GetCSharpMessage"); if (getMsg != NULL) { const char* result = getMsg(); printf("C#返回:%s\n", result); // 注意:如果返回的字符串是C#分配的,需要额外实现释放方法避免内存泄漏 } FreeLibrary(csDll); } return 0; } - 你之前用
dllExport无效很大概率是因为32位C尝试加载64位DLL,位数不匹配导致加载失败,统一为64位后就能正常工作。
内容的提问来源于stack exchange,提问作者Marco Bevilacqua
相关产品推荐
相关产品推荐

