使用JNI调用第三方.NET DLL

时间:2012-04-08 12:36:07

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

我正在尝试从JAVA程序中调用第三方.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对象和方法?

2 个答案:

答案 0 :(得分: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程序集(基于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;
}

答案 1 :(得分:1)

这正是本地Java到.NET Bridges在后台所做的事情。

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

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

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

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