2010-08-04 2 views
4

Я использую jni4net для доступа к Java-коду из приложения C# и наоборот. jni4net использует отражение для создания прокси-кода JNI-кода, поэтому очевидно, что одно из ограничений заключается в том, что ваш код Java и C# должен скомпилироваться для создания прокси.Двухсторонний объект, проходящий через jni4net (был: Игнорировать Missing Class (es))

К сожалению, это может привести к проблеме catch-22. Рассмотрим:

C# класс X использует Java класс Y
Java класс Y использует C# класс X

Ни может быть составлен, поэтому хорошо установлено временное решение взять один из классов (или X или Y), разделите его на свою голую подпись и попросите его скомпилировать, а затем сгенерируйте прокси-сервер из скомпилированного скелета. Затем вы можете заменить разделенный класс оригиналом и продолжить свой весёлый путь.

Это кажется уродливым подходом ко мне, и я считаю, что должен быть лучший способ. Очевидным решением было бы рассказать компилятору (либо C#, либо Java, на самом деле неважно) игнорировать ссылки на отсутствующий класс.

Не игнорирует ссылки на некоторый недостающий класс, допустимый для компиляторов C# или Java? Есть ли лучший способ сделать это (и нет, я не открыт для рассмотрения сокетов или чего-то подобного, мне нужен настоящий interop между .NET и Java)?

Пример кода было предложено:

Пример кода с кодом jni4net моста удален для ясности. IA и IB простые интерфейсы также не включены.

Java:

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

Я решил решить эту проблему самостоятельно. Это не связано с моей первоначальной догадкой, поэтому я изменил название этой проблемы, чтобы лучше отразить актуальную проблему.

В то время как в пакете jni4net есть много полезных примеров, казалось, что не было никаких хороших объектов, показывающих объект, проходящий в обоих направлениях, без какой-либо странной сборки гимнастики (см. Оригинальную постановку задачи). Я понял, как это сделать, и представим решение здесь вместе с командами, необходимыми для построения результата.

Самый простой способ получить это работает - настроить jni4net, как говорят инструкции, и отбросить все эти материалы в новый подкаталог каталога примеров, который поставляется с пакетом jni4net.

Сначала C# код:

SRC/тест/влево.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/тест/iright.java

package test; 

public interface iright 
{ 
    void announceMyself(); 
} 

SRC/тест/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..."); 
    }  
} 

И, наконец, сборка cript (я построил его для запуска в 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 
+1

Построение гимнастики все еще существует, вы просто автоматизировали их скриптом сборки. – Hassan

0

В C# 4, вы можете быть в состоянии использовать динамический ключевое слово при обращении к объекту Java. Не пробовал свой сценарий точно. Некоторый пример кода поможет.

редактирования для обновленного вопроса
У вас есть циклическую зависимость, что один компилятор, вероятно, жаловаться, не говоря уже о двух. Рефакторинг на что-то более похожее на следующее поможет. Конечно, это, вероятно, будет не так просто в вашем реальном коде.

// 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(); 
    } 
} 
+0

См. пример кода, который я только что добавил. –

+0

Да, я не уверен, что это сработает для моего варианта использования, но тем не менее это интересный подход. –