使用 JNA 调用具有依赖项的 DLL 报错 Invalid memory access ,请问如何解决?

新手上路,请多包涵

我在 C# 中创建了两个 dll 库,shuchu.dll 和 yinyong.dll

shuchu dll 的内容

namespace shuchu
{
    public class Class1
    {

        [DllExport("getInfo", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
        public static String GetInfo() {
            return "A1B2C3";
        }
    }
}

yinyong dll 的内容

namespace yinyong
{
    public class Ying
    {
        [DllExport("getShuChuInfo", CallingConvention = CallingConvention.Cdecl)]
        public static string GetShuChuInfo()
        {
            return Class1.GetInfo();
        }

        [DllExport("getNormalInfo", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
        public static string GetNormalInfo(string info)
        {
            return info;
        }
    }
}

yingyong.dll 中的 GetShuChuInfo 调用 GetInfo shuchu.dll不执行任何操作并返回调用方法的信息

他们都使用 offline.DllExport.1.7.4.29858 工具创建 ,DLL 都是 64 位的

这是我的 java 代码


public class NuoWenTest {
 private static String basePath = "D:\\WorkSpace\\EclipseWorkSpace\\HC_Exmple\\NuoWen";

    public interface NewtonsoftJsonDll extends Library {
        NewtonsoftJsonDll INSTANCE = Native.load("shuchu.dll",NewtonsoftJsonDll.class, W32APIOptions.ASCII_OPTIONS);

        String getInfo();
    }

    public interface Dll extends Library {
        NewtonsoftJsonDll INSTANCE = NewtonsoftJsonDll.INSTANCE;
        Dll dll = (Dll) Native.synchronizedLibrary(Native.load("yinyong.dll", Dll.class, W32APIOptions.ASCII_OPTIONS));

        String getShuChuInfo();

        String getNormalInfo(String info);

    }

    public static void main(String[] args) {

        System.setProperty("jna.debug_load", "true");
        System.setProperty("jna.debug_load.jna", "true");
        System.setProperty("jna.library.path", basePath);
        System.out.println(System.getProperty("os.arch"));
        System.setProperty("jna.encoding", "GBK");

        String value = "inputValue";
        String normalInfo = Dll.dll.getNormalInfo(value);
        System.out.println(normalInfo);
        String shuChuInfo = Dll.dll.getShuChuInfo();
        System.out.println(shuChuInfo);

    }
}

执行结果


amd64
一月 10, 2025 1:32:31 下午 com.sun.jna.Native extractFromResourcePath
信息: Looking in classpath from sun.misc.Launcher$AppClassLoader@18b4aac2 for /com/sun/jna/win32-x86-64/jnidispatch.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.Native extractFromResourcePath
信息: Found library resource at jar:file:/D:/maven/localRepository/net/java/dev/jna/jna/5.12.1/jna-5.12.1.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.Native extractFromResourcePath
信息: Extracting library to C:\Users\PC\AppData\Local\Temp\jna-2547\jna7403058685325327933.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.Native loadNativeDispatchLibraryFromClasspath
信息: Trying C:\Users\PC\AppData\Local\Temp\jna-2547\jna7403058685325327933.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.Native loadNativeDispatchLibraryFromClasspath
信息: Found jnidispatch at C:\Users\PC\AppData\Local\Temp\jna-2547\jna7403058685325327933.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Looking for library 'shuchu.dll'
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Adding paths from jna.library.path: D:\WorkSpace\EclipseWorkSpace\HC_Exmple\NuoWen
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Trying D:\WorkSpace\EclipseWorkSpace\HC_Exmple\NuoWen\shuchu.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Found library 'shuchu.dll' at D:\WorkSpace\EclipseWorkSpace\HC_Exmple\NuoWen\shuchu.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Looking for library 'yinyong.dll'
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Adding paths from jna.library.path: D:\WorkSpace\EclipseWorkSpace\HC_Exmple\NuoWen
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Trying D:\WorkSpace\EclipseWorkSpace\HC_Exmple\NuoWen\yinyong.dll
一月 10, 2025 1:32:31 下午 com.sun.jna.NativeLibrary loadLibrary
信息: Found library 'yinyong.dll' at D:\WorkSpace\EclipseWorkSpace\HC_Exmple\NuoWen\yinyong.dll
inputValue
Exception in thread "main" java.lang.Error: Invalid memory access
    at com.sun.jna.Native.invokePointer(Native Method)
    at com.sun.jna.Function.invokePointer(Function.java:497)
    at com.sun.jna.Function.invokeString(Function.java:660)
    at com.sun.jna.Function.invoke(Function.java:434)
    at com.sun.jna.Function.invoke(Function.java:361)
    at com.sun.jna.Library$Handler.invoke(Library.java:265)
    at com.sun.jna.Native$3.invoke(Native.java:1252)
    at com.sun.proxy.$Proxy1.getShuChuInfo(Unknown Source)
    at com.kaimingyun.iccard.controller.NuoWenTest.main(NuoWenTest.java:37)

如果调用 getNormalInfo,则不会报告错误,但调用了具有外部dll的方法getShuChuInfo()就会报错

java 版本为 1.8,JNA 版本为 5.12.1,使用 Windows 11,CPU i7-12700k,32GB RAM

我猜是依赖关系导致的问题 但不知道如何解决

我尝试将 getShuChuInfo() 方法的返回类型更改为 WString 和 Pointer,但它们都返回相同的错误。

阅读 623
avatarAI BotBETA

回答

问题出现在 Java 使用 JNA 调用 C# 编写的 DLL 时,特别是当涉及到 DLL 之间的依赖关系时。在您的例子中,yinyong.dll 依赖于 shuchu.dll,但在 JNA 中处理这种依赖关系时可能会遇到一些问题。

解决方案

  1. 确保 DLL 路径正确

    • 确保 shuchu.dllyinyong.dll 都位于 Java 应用程序可以访问的路径中,并且路径已正确设置在 jna.library.path 系统属性中。
  2. 使用 System.loadLibrary 而不是 Native.load

    • 在 Java 中,尝试使用 System.loadLibrary 而不是 Native.load 来加载 DLL。System.loadLibrary 依赖于系统的库加载机制,它可能更好地处理 DLL 之间的依赖关系。
    • 需要注意的是,使用 System.loadLibrary 时,不需要指定 DLL 的文件扩展名或路径,只需提供 DLL 的名称(不包括 .dll)。因此,确保 DLL 文件位于系统的 PATH 环境变量所指定的目录中,或者将它们复制到 Java 应用程序的工作目录中。
  3. 更新 JNA 接口定义

    • 确保您的 JNA 接口定义与 C# DLL 中的导出函数完全匹配。特别是函数名称、调用约定和参数类型。
  4. 检查字符串编码

    • 由于您的 C# DLL 使用 UTF-16 编码的字符串(.NET 默认的字符串编码),而 Java 使用 UTF-8 或其他编码,这可能会导致字符串在传递时出现问题。尽管 JNA 通常能够处理这种编码差异,但在某些情况下,特别是当涉及到复杂的字符串处理时,可能会遇到问题。
    • 尝试在 C# DLL 中将字符串转换为字节数组,然后在 Java 中进行相应的解码,或者使用其他方法来确保字符串的正确传递。
  5. 调试和日志记录

    • 在 C# DLL 中添加日志记录,以查看 GetShuChuInfo 方法是否被正确调用,以及 Class1.GetInfo 方法是否返回了预期的结果。
    • 在 Java 代码中添加更多的异常处理和日志记录,以便在出现问题时能够获取更多的上下文信息。
  6. 考虑使用其他跨语言调用技术

    • 如果问题持续存在,您可以考虑使用其他技术来在 Java 和 C# 之间进行跨语言调用,如 COM(如果适用)、C++/CLI(如果您可以编写一个中间的 C++/CLI 库来桥接 Java 和 C#)或通过网络通信(如 REST API 或 gRPC)。

通过上述步骤,您应该能够诊断并解决问题,或者至少能够缩小问题的范围。如果问题仍然存在,您可能需要更深入地调查 JNA 和 .NET 之间的互操作性细节。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏