【问题标题】:Calling a 3rd party .NET DLL using JNI使用 JNI 调用第 3 方 .NET DLL
【发布时间】:2012-04-08 12:36:06
【问题描述】:

我正在尝试从 JAVA 程序中调用第 3 方 .NET DLL(取自 here)。 在查看herehere 之后,我设法让整个东西编译并运行。但是在运行 .NET 代码时出现异常:

Java 运行时环境检测到致命错误

只有当我尝试从 .NET DLL 中访问另一个 .net 对象和方法时才会发生这种情况:

JNIEXPORT void JNICALL Java_test_broadcast
(JNIEnv *, jobject)
{
   // Instantiate the MC++ class.
   IManagedWrapper* t = IManagedWrapper::CreateInstance();

   // The actual call is made. 
   t->Broadcast();
}

void ManagedWrapper::Broadcast(std::string message)
{
   //Uncommenting the following line will raise the error
   //IXDBroadcast^ broadcast = XDBroadcast::CreateBroadcast(XDTransportMode::WindowsMessaging);
}

我设法创建了一个 .NET DLL,它链接到上述代码并按需要工作。

如何从 Java 代码中调用 .NET 对象和方法?

【问题讨论】:

  • Google 向我展示了:JNI4NETCalling .Net Dlls from Java code without using regasm.exe。如果您愿意并坚持下去,它可能会为您提供更多解决方案。
  • 谢谢!我在这里发帖前找了 2 天,但我从未遇到过您发布的第二个链接。成功了!
  • 不客气,祝你好运。
  • 我想知道是否有人拥有@HovercraftFullOfEels 引用的第二个链接中的代码 - 它已从页面中消失。

标签: java .net dll java-native-interface


【解决方案1】:

我终于在 cmets 中关注了@“Hovercraft Full Of Eels”链接: Calling .Net Dlls from Java code without using regasm.exe

我使用 C++\CLI 在本机代码和托管代码之间架起一座桥梁,它运行良好。 主要问题是我的桥 DLL 在 JVM 下运行,而我尝试加载的 DLL 不在 JRE\bin 目录中。为了克服这个问题,我从 C++/CLI 代码中动态加载了 .Net 程序集(基于this):

static Assembly^ MyResolveEventHandler( Object^ sender, ResolveEventArgs^ args )
{
    //Retrieve the list of referenced assemblies in an array of AssemblyName.
    Assembly^ MyAssembly;
    Assembly^ objExecutingAssemblies;
    String^ strTempAssmbPath = "";

    objExecutingAssemblies = Assembly::GetExecutingAssembly();
    array<AssemblyName ^>^ arrReferencedAssmbNames = objExecutingAssemblies->GetReferencedAssemblies();

    //Loop through the array of referenced assembly names.
    for each (AssemblyName^ strAssmbName in arrReferencedAssmbNames)
    {
        //Check for the assembly names that have raised the "AssemblyResolve" event.
        if (strAssmbName->FullName->Substring(0, strAssmbName->FullName->IndexOf(",")) == args->Name->Substring(0, args->Name->IndexOf(",")))
        {
            //Build the path of the assembly from where it has to be loaded.                
            strTempAssmbPath = pathBase + args->Name->Substring(0, args->Name->IndexOf(",")) + ".dll";
            break;
        }

    }
    //Load the assembly from the specified path.                    
    MyAssembly = Assembly::LoadFrom(strTempAssmbPath);

    //Return the loaded assembly.
    return MyAssembly;
}

【讨论】:

  • 我有同样的情况(JVM 通过 JNI 到 DLL,然后 C++ 尝试使用托管 C# DLL 并失败)但我从未收到来自 AssemblyResolve 事件的回调。
【解决方案2】:

这正是原生 Java 到 .NET 桥在后台所做的事情。

根据您需要使用的 .NET 代码数量和 .NET 对象的复杂性(您有什么样的方法,如果您使用泛型,是否有数组等),您也可以考虑使用这种桥接器.当您更深入地研究这种情况时,如果您自己通过 C++/CLI 手动进行,则会出现一个又一个的限制。如果您需要快速可靠的生产环境解决方案,我建议您检查:

这些桥中的每一个都将为您提供所有本机通信,并提供非常简单的界面,以便使用 .NET 加载任何 DLL,甚至在您的 JAVA 应用程序中使用整个 .NET Framework。

根据您的需要,Javonet 我认为它是最简单且非常轻便的一种,具有强大的功能和灵活性,如果您正在寻找具有良好支持和简单 API 的可靠商业解决方案来完成工作,那么它绝对有用在 5 分钟内(非商业和学术免费)。 JNBridge 更强大的强类型代理类生成器也非常强大,也非常适合商业用途,特别是如果您需要它们的任何专用连接器(影响价格,但取决于您的需求)。 JNI4NET 不错的开源项目,我会说它适用于非关键、非商业应用,但值得一试。

有了这样的桥,你不需要关心任何额外的实现,只需复制 .NET dll 并在 JAVA 中使用它。你可以在这里看到它:http://www.youtube.com/watch?v=n6XfzrHTdK4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多