4

我正在使用 jni4net 从 C# 应用程序中访问 Java 代码,反之亦然。jni4net 使用反射来生成 JNI 代码代理,因此显然限制之一是您的 Java 和 C# 代码必须编译才能构建代理。

不幸的是,这可能会导致 catch-22 问题。考虑:

C# 类 X 使用 Java 类 Y
Java 类 Y 使用 C# 类 X

两者都不能编译,因此完善的解决方法是采用其中一个类(X 或 Y),将其剥离到其裸签名并对其进行编译,然后从编译的骨架生成代理。然后,您可以将剥离的课程替换为原始课程,然后继续您的快乐之路。

这对我来说似乎是一种丑陋的方法,我相信应该有更好的方法。一个明显的解决方案是告诉编译器(无论是 C# 还是 Java,哪个都无所谓)忽略对缺失类的引用。

对于 C# 或 Java 编译器,忽略对某个缺失类的引用是否可行?有没有更好的方法来做到这一点(不,我不愿意考虑套接字或任何类似性质的东西;我需要.NET 和 Java 之间的真正互操作)?

请求示例代码:

为清楚起见,删除了 jni4net 桥接代码的示例代码。IA 和 IB 是简单的接口,也不包括在内。

爪哇:

public class A implements IA  
{  
    public void m1()  
    {  
        System.out.println("m1 called");  
    }  

    public static void main (String args[])  
    {  
        IB b = new B();  
        b.m2(new A());  
    }  
}  

C#:

public class B : IB  
{  
    public void m2(IA a)  
    {  
        a.m1();  
        A a2 = new A();  
        a2.m1();  
    }  
}  
4

2 回答 2

4

我最终自己解决了这个问题。它没有涉及我最初的预感,所以我更改了这个问题的标题以更好地反映实际问题。

虽然 jni4net 包有很多有用的示例,但似乎没有任何好的示例显示对象在没有一些奇怪的构建体操的情况下双向传递(参见原始问题陈述)。我想出了如何做到这一点,并在此处介绍了解决方案以及构建结果所需的命令。

运行此程序的最简单方法是按照说明设置 jni4net,并将所有这些内容放入 jni4net 软件包随附的示例目录的新子目录中。

首先是 C# 代码:

src/test/left.cs

namespace test
{
    using System;
    using net.sf.jni4net;
    using test;

    public class left : iright
    {
        public static void Main(String[] args)
        {
            left l = new left();
            l.sendMeToRight();
        }

        public left()
        {
            Console.WriteLine("left side constructed...");
        }

        public void sendMeToRight()
        {
            BridgeSetup bridgeSetup = new BridgeSetup();
            bridgeSetup.AddAllJarsClassPath(".");
            Bridge.CreateJVM(bridgeSetup);
            Bridge.RegisterAssembly(typeof(right).Assembly);

            Console.WriteLine("Sending myself to right.");
            right il = new right(this);
            il.announceMyself();
        }

        public void announceMyself()
        {
            Console.WriteLine("Hello from the left side...");
        }
    }
}

现在是 Java 代码:

src/test/iright.java

package test;

public interface iright
{
    void announceMyself();
}

src/test/right.java

package test;

public class right implements iright
{
    public right(iright f)
    {
        System.out.println("right side constructed... ");
    f.announceMyself();
    }

    public void announceMyself()
    {
        System.out.println("Hello from the right side...");  
    }    
}

最后是构建脚本(我构建它以在 cygwin 中运行,并且在很短的时间内通知,因此根据需要进行更改。):

@echo off
rm -rf build
mkdir build
mkdir build\test
copy ..\..\lib\*.* build

echo Compile base classes.
javac src/test/*.java
mv src/test/*.class build/test

echo Creating jar file.
jar cvf build\lr.jar -C build test/iright.class -C build test/right.class
rm build/test/*.class

echo Generating proxies.
..\..\bin\proxygen.exe build\lr.jar -wd build

echo Compiling derived proxy classes.
javac -cp build\lr.jar;build\jni4net.j-0.8.0.0.jar build\jvm\test\iright_.java build\jvm\test\right_.java

echo Packing compiled derived proxy classes.
jar cvf build\lr.j4n.jar -C build\jvm test\__iright.class -C build\jvm test\iright_.class -C build\jvm test\right_.class

echo Generating derived proxy DLL.
cd build
csc.exe /nologo /warn:0 /t:library /out:lr.j4n.dll /recurse:clr\*.cs /reference:"c:\windows\microsoft.net\framework\v2.0.50727\mscorlib.dll" /reference:jni4net.n-0.8.0.0.dll

echo Generating product executable.
csc.exe /nologo /warn:0 /out:demo.exe /target:exe /reference:jni4net.n-0.8.0.0.dll /reference:lr.j4n.dll ..\src\test\left.cs
于 2010-08-06T00:05:11.297 回答
1

在 C# 4 中,您可以在访问 Java 对象时使用 dynamic 关键字。还没有完全尝试过你的场景。一些示例代码会有所帮助。

编辑更新的问题
您有一个循环依赖,单个编译器可能会抱怨,更不用说两个了。重构为类似以下的内容会有所帮助。当然,在您的真实代码中可能不会那么简单。

// java
public class A implements IA  
{  
    public void m1()  
    {  
        System.out.println("m1 called");  
    }  
}

public class MainClass
{
    public static void main (String args[])  
    {  
        IB b = new B();  
        b.m2(new A());  
    }  
}  

//C#

public class B : IB  
{  
    public void m2(IA a)  
    {  
        a.m1();  
        A a2 = new A();  
        a2.m1();  
    }  
}
于 2010-08-04T23:35:11.483 回答