Reputation: 511
I have a project written in Kotlin, and I want to use a library written in C#. So I used the JNI to make a "proxy" in C++ witch make the link between C# and the JVM.
I was able to load
the library in Kotlin but I have this error when I call a function:
Fatal error. System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception.
at <Module>.Java_Authenticator_authenticate(JNIEnv_*, _jobject*, _jstring*, _jstring*)
:run (Thread[Execution worker for ':' Thread 2,5,main]) completed. Took 1.965 secs.
This is my Java class witch use the library:
public class Authenticator {
static {
System.loadLibrary("CppProxy");
}
public native boolean authenticate(String username, String password);
public void runLib() {
System.out.println("run");
boolean valid = authenticate("admin", "admin");
if(valid) {
System.out.println("Valid");
}
else {
System.out.println("No valid");
}
}
}
This is the Authenticator.h file in C++ project, generated automatically with the command javac -h
:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Authenticator */
#ifndef _Included_Authenticator
#define _Included_Authenticator
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Authenticator
* Method: authenticate
* Signature: (Ljava/lang/String;Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_Authenticator_authenticate
(JNIEnv *, jobject, jstring, jstring);
#ifdef __cplusplus
}
#endif
#endif
This is my CppProxy.cpp file:
#include "pch.h"
#include "CppProxy.h"
#include <string.h>
#include "Authenticator.h"
String^ toString(const char* chars) {
int len = (int)strlen(chars);
array<unsigned char>^ a = gcnew array<unsigned char>(len);
int i = 0;
while (i < len) {
a[i] = chars[i];
i++;
}
return System::Text::Encoding::UTF8->GetString(a);
}
bool authenticate(const char* username, const char* password) {
return LibreHardwareMonitorWrapper::SharpAuthenticator::SharpAuthenticated(toString(username), toString(password));
}
JNIEXPORT jboolean JNICALL Java_Authenticator_authenticate
(JNIEnv* env, jobject c, jstring username, jstring password) {
jboolean isCopyUsername;
const char* c_username = env->GetStringUTFChars(username, &isCopyUsername);
jboolean isCopyPassword;
const char* c_password = env->GetStringUTFChars(password, &isCopyPassword);
jboolean result = authenticate(c_username, c_password);
// cleaning
env->ReleaseStringUTFChars(username, c_username);
env->ReleaseStringUTFChars(username, c_password);
return result;
}
And this is my C# code:
namespace LibreHardwareMonitorWrapper
{
public static class SharpAuthenticator
{
public static bool SharpAuthenticated(String username, String password)
{
return username == "admin" && password == "admin";
}
}
}
I'm using the oracle JDK 17 and the C# project is currently using .NET6.
Cpp project target x64 platform and C# project Any CPU.
The Cpp project is build in a folder call "lib" witch is inside java.library.path
.
CppProxy
has for reference LibreHardwareMonitorWrapper
.
I tried to run .\gradlew run
and expected to see Valid
but I have an error in my external function at execution.
Upvotes: 1
Views: 165
Reputation: 29
Finally found what was the problem. I could not find the CLR option in properties of C# project, whereas it's crucial for running C# code in C++.
So I think .net6 is not yet compatible with this option, I tried with .net framework 4.x and it works.
Also, you should know that it is necessary to put the assemblies of C# project in the /bin of JDK.
Upvotes: 1