使用JNA调用C# DLL触发Invalid memory access错误求助
JNA调用C#导出DLL时出现Invalid memory access的排查方案
以下是几个常见的排查方向,按优先级排序:
参数/返回值类型映射必须完全匹配
比如C#定义的int _Add(int a, int b),JNA接口里必须对应int _Add(int a, int b),不能出现类型错配(比如把C#的int对应成JNA的long,或者反过来)。如果涉及引用/输出参数,C#的ref int/out int要对应JNA的IntByReference,不能直接传基本类型。示例:// 对应C#的void _Add(ref int result, int a, int b) void _Add(IntByReference result, int a, int b);调用时需要实例化
IntByReference传入,再通过getValue()获取结果。对齐调用约定
DllExport默认使用stdcall调用约定,但JNA默认用cdecl。必须在JNA加载DLL时显式指定匹配的调用约定:public interface MyDll extends Library { MyDll INSTANCE = Native.load("YourDllName", MyDll.class, Map.of(Library.OPTION_CALLING_CONVENTION, CallingConvention.STDCALL)); int _Add(int a, int b); }如果你在C#导出时修改了调用约定(比如
CallingConvention.Cdecl),JNA这边也要同步改成CallingConvention.CDECL。核对导出方法的真实名称
用dumpbin查看导出表时,注意是否存在名字修饰(比如stdcall会生成_Add@8这类带后缀的名称)。如果有修饰,要么在JNA接口里使用全名,要么在C#导出时指定无修饰的名称:[DllExport("_Add", CallingConvention = CallingConvention.StdCall)] public static int Add(int a, int b) { return a + b; }确保DLL与JVM位数一致
64位的C# DLL必须搭配64位JVM运行,32位DLL必须搭配32位JVM。位数不匹配会直接触发内存访问错误,这个是高频踩坑点。复杂类型的内存管理检查
如果方法涉及字符串、结构体等复杂类型:- C#返回字符串时,不能直接返回
string,需要用Marshal.AllocHGlobal分配非托管内存,JNA读取后要调用Native.free()释放; - 结构体定义必须严格对齐字段顺序、类型和内存布局,C#用
[StructLayout(LayoutKind.Sequential)],JNA要对应@Structure.FieldOrder({"field1", "field2"})。
- C#返回字符串时,不能直接返回
内容的提问来源于stack exchange,提问作者suman sourav
相关产品推荐
相关产品推荐

