【问题标题】:How to use C# function in Java using JNA lib如何使用 JNA lib 在 Java 中使用 C# 函数
【发布时间】:2013-08-27 20:01:32
【问题描述】:

我花了很多时间尝试在我的 Java 应用程序中使用 C# 函数,但没有成功... 我用 C# 编写了以下库:

public class Converter
{

    public Converter()
    {
    }

    public bool ConvertHtmlToPdf(String directoryPath)
    {
        //DO SOMETHING
    }
}

这个 dll 调用另一个 dll 进行一些操作,但是当我编译它时,我可以在我的 Realse 文件夹中找到 Dll,一切似乎都正常,所以我使用 32 位选项、64 位和任何 CPU 选项编译它只是为了确保这不是我的问题。

使用 32 位 Dependency Walker 和任何 CPU 选项分析我的 dll 文件,它说找不到 IESHIMS.DLL,并显示此消息:

警告:未找到至少一个延迟加载依赖模块。 警告:由于延迟加载依赖模块中缺少导出功能,至少有一个模块存在未解析的导入。

64 位文件不会出现这种情况,但我找不到我的 ConvertHtmlToPdf 函数。

由于我不知道它是否相关,我的第二步是在 Java 代码中。

要加载我的库,我会这样做:

System.setProperty("jna.library.path", "C:\\Program Files (x86)\\Facilit\\Target App\\lib");

和:

public interface IConversorLibrary extends Library {

    IConversorLibrary INSTANCE = (IConversorLibrary) Native.loadLibrary("converter", IConversorLibrary.class);

    void ConvertHtmlToPdf(String directoryPath);
}

(lib 似乎加载成功,因为如果我尝试在我的应用程序运行时删除 dll 文件,它会说无法删除,因为它正在使用中) 最后:

IConversorLibrary.INSTANCE.ConvertHtmlToPdf(directoryPath);

但结果并不如我所愿:

java.lang.UnsatisfiedLinkError: Error looking up function 'ConvertHtmlToPdf': Could not find the specified procedure.

我不知道自己做错了什么,我尝试了很多教程和很多东西,但似乎一切都有效,非常感谢任何帮助。

【问题讨论】:

  • 设置jna.library.path 并不会真正影响JNA;你需要设置%PATH%。后者实际上会影响共享库的加载,jna.library.path 不会。
  • 如果在dependency walker中没有看到你的函数名,JNA肯定是找不到的。
  • JNA 可以从使用 C 链接的 DLL 加载。默认情况下,C# 类不支持任何类型的 C 链接。 C++ 支持使用 extern "C" 表示法的 C 链接。
  • @technomage 有没有办法让 JNA “找到”它?一些教程,或者只是一个想法?
  • This article 建议你可以破解 C# DLL 加载来做你想做的事。

标签: c# java dll jna


【解决方案1】:

正如technomage所说:

JNA 可以从使用 C 链接的 DLL 加载。 C# 类不通过 默认支持任何类型的 C 链接。 C++ 支持 C 与 外部“C”符号。

This article 展示了一种使 C# DLL 方法像 C 样式 DLL 一样可调用的方法,不幸的是它相当复杂。

【讨论】:

  • 链接失效
【解决方案2】:

这款 Nugget 非常易于使用且运行良好。 https://www.nuget.org/packages/UnmanagedExports

您需要 Visual Studio 2012 (express)。 安装后,只需在要导出的任何静态函数之前添加[RGiesecke.DllExport.DllExport]。就是这样!

示例:

C#

[RGiesecke.DllExport.DllExport]
public static int YourFunction(string data)
{
     /*Your code here*/
     return 1;
}

Java

在顶部添加导入:

   import com.sun.jna.Native;

在你的类中添加接口。它是你的 C# 函数名,前面有字母“I”:

  public interface IYourFunction extends com.sun.jna.Library
    {
       public int YourFunction(String tStr);
    };

在课堂上需要的地方调用 DLL:

IYourFunction iYourFunction = (IYourFunction )Native.loadLibrary("full or relative path to DLL withouth the .dll extention", IYourFunction.class);//call JNA
        System.out.println("Returned: " + IYourFunction.YourFunction("some parameter"));

【讨论】:

  • 真的吗?我试试看:D
  • 我自己试过了。非常容易。唯一需要注意的是处理器架构,它必须在 VS 中的项目和单元测试项目之间匹配,您在 VS 中的默认处理器架构设置在 Test |测试设置 |默认处理器架构,以及加载 .dll 的互操作环境的位数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-23
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多