4

我正在尝试从 JAVA 程序中调用第 3 方 .NET DLL(取自此处)。在看了这里这里之后,我设法让整个东西编译和运行。但是在运行 .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 对象和方法?

4

2 回答 2

4

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

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

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;
}
于 2012-04-09T14:38:59.750 回答
1

这正是原生 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

于 2013-11-07T21:48:10.747 回答