У меня есть сторонняя сборка .NET и большое приложение Java. Мне нужно вызвать mothods, предоставленные библиотекой классов .NET из приложения Java. Сборка не поддерживает COM. Я обыскал сеть, и до сих пор у меня есть следующее:
Код С# (cslib.cs):
using System;
namespace CSLib
{
public class CSClass
{
public static void SayHi()
{
System.Console.WriteLine("Hi");
}
}
}
скомпилирован с использованием .net 3.5, но то же самое происходит при использовании 2.0):
csc /target:library cslib.cs
Код С++ (clib.cpp):
#include <jni.h>
#using <CSLib.dll>
using namespace CSLib;
extern "C" _declspec(dllexport) void Java_CallCS_callCS(JNIEnv* env, jclass cls) {
CSLib::CSClass::SayHi();
}
скомпилирован (с использованием инструментов VC 2008, но то же самое происходит при использовании инструментов 2003):
cl /clr /LD clib.cpp
mt -manifest clib.dll.manifest -outputresource:clib.dll;2
Код Java (CallCS.java):
class CallCS {
static {
System.loadLibrary("clib");
}
private static native void callCS();
public static void main(String[] args) {
callCS();
}
}
Когда я пытаюсь запустить класс java, Java VM сбой при вызове метода (он может загружать библиотеку):
# # An unexpected error has been detected by Java Runtime Environment: # # Internal Error (0xe0434f4d), pid=3144, tid=3484 # # Java VM: Java HotSpot(TM) Client VM (10.0-b19 mixed mode, sharing windows-x86) # Problematic frame: # C [kernel32.dll+0x22366] # ... Java frames: (J=compiled Java code, j=interpreted, Vv=VM code) j CallCS.callCS()V+0 j CallCS.main([Ljava/lang/String;)V+0 v ~StubRoutines::call_stub
Однако, если я создаю простое приложение cpp, которое загружает clib.dll и вызывает экспортированную функцию Java_CallCS_callCS, все в порядке. Я пробовал это в обеих средах x86 и x64, и результат тот же. Я не пробовал другие версии Java, но мне нужен код для запуска на 1.5.0.
Кроме того, если я изменяю clib.cpp для вызова только системных методов, все работает отлично даже с Java:
#include <jni.h>
#using <mscorlib.dll>
using namespace System;
extern "C" _declspec(dllexport) void Java_CallCS_callCS(JNIEnv* env, jclass cls) {
System::Console::WriteLine("It works");
}
Завершить:
- Я могу позвонить системным методам из Java → clib.dll → mscorlib.dll
- Я могу использовать любые методы из CPPApp → clib.dll → cslib.dll
- Я UNABLE для вызова любых методов из Java → clib.dll → cslib.dll
Мне известно об обходном пути, который использует 1. выше. Я могу использовать рефлексию для загрузки assmebly и вызова желаемых методов, используя только системные вызовы, но код становится беспорядочным, и я надеюсь на лучшее решение.
Я знаю о проекте dotnetfromjava, который использует метод отражения, но предпочитает не добавлять больше сложности, чем нужно. Я буду использовать что-то вроде этого, если нет другого способа, однако.
Я тоже посмотрел на ikvm.net, но я понимаю, что он использует свою собственную JVM (написанную на С#) для совершения магии. Тем не менее, запуск всего приложения Java под его VM не является для меня вариантом.
Спасибо.