- 建一个解决方案,包含3个工程:WIN32 DLL 、控制台应用(c)、控制台应用(c#)
- WIN32 DLL代码:
#ifdef __cpluscplus #define EXPORT extern "C" __declspec(dllexport) #else #define EXPORT __declspec(dllexport) #endif EXPORT int add(int x, int y) { return (x + y); }
- 控制台应用(c):
#include <stdio.h> #include <windows.h> typedef int (*func)(int x, int y); int main(int argc, char *argv[]) { HMODULE hDll = LoadLibrary("dll.dll"); func add = (func)GetProcAddress(hDll, "add"); int n = add(3, 4); printf("3 + 4 = %d ", n); FreeLibrary(hDll); getchar(); }
- 控制台应用(c#):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace exe_cs { class Program { [DllImport("dll.dll", EntryPoint = "add", CallingConvention = CallingConvention.Cdecl)] public extern static int add(int x, int y); static void Main(string[] args) { int n = add(3, 4); Console.WriteLine("3 + 4 = {0} ", n); Console.Read(); } } }
- 注意事项
- C# DllImport中,CallingConvention = CallingConvention.Cdecl很关键,尤其是vs2012。编译C的dll时,使用cdecl调用方式,而C#导入dll中函数时,使用Stdcall。如果不设置运行出现异常: 调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。