Как вызвать внешнюю функцию DLL из кода Java
4 ответа
Я наткнулся на ту же проблему "вызова DLL из Java" и сначала был разочарован сложностью. Тем не менее, есть элегантное решение (может быть также интересным для людей, живущих там в месте обитания processing.org.) Учитывая довольно "общую" форму вопроса (возможно, понижение рейтинга не оправдано для этого), я полагаю, было бы указано довольно легкое решение. Другими словами, решение, позволяющее избежать путаницы с заголовочными файлами, дополнительными преобразованиями и т. Д., Так же как и исходный код, не обязательно доступно.
Моя рекомендация для этого была бы JNA ( https://github.com/twall/jna), которая в основном является упрощающей оболочкой для JNI. Это прекрасно работает, отображение типов является простым (например, pchar = lpcstr buffer -> string), хотя я использую его только для библиотек Windows и моих собственных библиотек C-стиля, созданных с использованием Delphi-Pascal. Единственное, что нужно учитывать, - это то, что возвращаемые значения должны экспортироваться через функции, а не "помеченные" ссылочные переменные. Вопрос уже указывает на связанный источник, который обеспечивает пример для этого (таким образом, ответы вокруг JNI могут быть здесь неуместны). Обратите внимание, что ссылка, которую я предоставил, также содержит примеры для переноса массивов и указателей.
Вам нужно будет использовать собственный интерфейс Java (JNI), который представляет собой набор функций C/C++, которые позволяют нативному коду взаимодействовать с кодом Java (т. Е. Получать параметры из вызовов функций Java, возвращать результаты и т. Д.). Напишите библиотеку C-оболочки, которая принимает вызовы JNI, а затем вызывает вашу внешнюю библиотеку.
Например, следующая функция вызывает метод updateHandlers
на нативный объект (который хранится так же долго на стороне Java).
class MyImpl {
void updateHandlers(JNIEnv *env) {
this->contentHandler = ....;
}
}
JNIEXPORT void JNICALL Java_package_Classname_updateHandlers0
(JNIEnv *env, jobject obj, jlong ptr)
{
((MyImpl*)ptr)->updateHandlers(env);
}
Соответствующие объявления в package.ClassName:
private long ptr; //assigned from JNI
public void updateHandlers() {
if (ptr==0) throw new NullPointerException();
updateHandlers0(ptr);
}
private native void updateHandlers0(long ptr);
static {
try {
/*try preloading the library external.dll*/
System.loadLibrary("external");
} catch (UnsatisfiedLinkError e) {
/*library will be resolved when loading myjni*/
}
System.loadLibrary("myjni"); //load myjni.dll
}
Некоторое время назад я написал пример учебного пособия, возможно, это поможет.
http://wendro.blogspot.com/2010/03/jni-example-eclipse-dev-cpp.html
Вы объявляете свои нативные функции в Java (native private ...
) с подписью, которая вам нужна; затем беги javah
(инструмент, который поставляется с JDK) для генерации собственных заголовков. List<String>
(на самом деле List
из-за типа стирания) является jobject
в нативном коде.
Соответствующий метод C будет:
JNIEXPORT jobject JNICALL package_Classname_getWords(JNIEnv *env, jobject jobj, jstring word)
Я думаю, что было бы проще вернуть массив строк jobjectArray
и создать экземпляр списка в Java из возвращенных значений. Смотрите этот пример.