0

我有一个要从Java 调用的第三方 VB.Net dll

VB.Net dll 具有以下签名(伪代码,但感觉像 Java...):

class MyClass1 {
    public Object method1(StringRef arg1, StringRef arg2) {
        // do something here...
        return someResult;
    }
}
class MyClass2 {
    public Object method2(StringRef arg1, StringRef arg2) {
        // do something here...
        return someOtherResult;
    }
}

注意: StringRef我的说法是该方法希望我通过引用传递字符串。

我试图从 Java 中调用这个 dll 对象。使用 JNA,我有以下内容:

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface DllName extends Library {
    DllName INSTANCE = (DllName)Native.loadLibrary("DllName", DllName.class);

    public static interface MyClass1 {
        public Object method1(String arg1, String arg2);
    }
    public static interface MyClass2 {
        public Object method2(String arg1, String arg2);
    }
}

这里的INSTANCE对象加载得很好。但是,我无法弄清楚主体DllName应该采用什么结构来映射到 dll 的类、方法签名。此外,我还没有看到如何Native以直接加载对象的方式调用。例如,如果我这样做:

DllName INSTANCE = (DllName)Native.loadLibrary("DllName.MyClass1", DllName.class);

这会导致UnsatisfiedLinkErrordll 被命名为DllName. 进行此调用需要与上面显示的接口不同的接口。

问题

  1. 这甚至可能吗?例如,在给定上述结构的情况下,我可以使用 JNA 从 Java 调用 VB.Net dll。
  2. 需要什么结构DllName才能正确映射到类MyClass1MyClass2?这是我的核心问题。
  3. 在上面的DllName.MyClass1电话中,有没有其他方法?
  4. 我是否错过了下面提到的任何替代项目?也许我错过了其他一些解决方案?

我探索了以下替代方案

  1. 查看了这篇文章,但没有看到与我的结构匹配的示例。我还查看了底部引用的单元测试。
  2. 创建一个 C++ 包装器,如此处建议的 /questions/1556421/use-jni-instead-of-jna-to-call-native-code (我会作为链接发布,但没有足够的声誉......)。我实际上没有尝试过,因为我不熟悉 C++。当我认为对我的 Java 代码进行一些更改就足够了时,我会期待太多的打击。
  3. JNI:这似乎只适用于 C/C++ 类型的 dll。
  4. javOnet:几乎可以工作,但是 VB.Net 方法需要通过引用来引用字符串,目前 javOnet 不支持。我向他们报告了这个问题,我希望得到修复。即使它确实有效,看起来 JNA 解决方案也应该有效。该解决方案还存在成本问题。
  5. jni4net:这对我不起作用,因为这是第三方 dll。jni4net 期望在 .Net 方面有一些钩子。

如果您希望我在这里添加任何其他颜色,请告诉我。

4

1 回答 1

0

从 1.2 版开始,javOnet 已经支持通过 ref 或 out 传递的参数。您可以在以下位置阅读更多信息: http ://www.javanet.com/quick-start-guide/#Passing_arguments_by_reference_with_ref_and_out_keywrods

您必须将 JAVA 类型包装在“AtomicReference”中,以便它可以在方法调用中更新,并且您的 JAVA 变量假设整数将在 .NET 端自动修改。您可以在下面看到使用示例:

NObject refEx = Javonet.New("RefExample");  
//Wrap Java integer in AtomicReference to allow passing by reference  
AtomicReference<Integer> myInt = new AtomicReference<Integer>(10);  

refEx.invoke("Method",new NRef(myInt));  

System.out.println(myInt.get());  
//Output will display number "55" because int passed by reference has been modified within the method body.
于 2014-04-10T12:35:25.487 回答