如何从 Java 调用 C# 函数

9
我需要从Java中调用C#函数,为此我创建了以下内容。 我已经创建了一个Java头文件Authenticator.h,以下是代码:
#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

我已经创建了一个C#函数来进行身份验证。
namespace SharpAuthenticator
{
    public class Authenticator
    {



        public  bool Authenticate(String username,String password)
        {
            return username == "user" && password == "login";
        }

    }
}

我试图使用以下代码从C++(创建dll项目)调用C#函数:

String^ toString(const char *str)
{
    int len = (int)strlen(str);
    array<unsigned char>^ a = gcnew array<unsigned char>(len);
    int i = 0;
    while (i < len)
    {
        a[i] = str[i];
        i++;
    }
    return Encoding::UTF8->GetString(a);
}
bool authenticate(const char *username, const char *password)
{
     SharpAuthenticator::Authenticator::Authenticate(toString(username), toString(password));

}
JNIEXPORT jboolean JNICALL Java_Authenticator_authenticate
(JNIEnv *env, jobject c, jstring name, jstring pass)
{
    jboolean result;

    jboolean isCopyUsername;
    const char * username = env->GetStringUTFChars(name, &isCopyUsername);
    jboolean isCopypassword;
    const char * password = env->GetStringUTFChars(pass, &isCopypassword);

    result = authenticate(username, password);
    env->ReleaseStringUTFChars(name, username);
    env->ReleaseStringUTFChars(pass, password);
    return result;
}

最后创建一个DLL文件,我需要从Java中调用它。DLL文件已经创建并在Java中成功加载,但是我在Java中得到了这个错误日志。我可能缺少什么。

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  Internal Error (0xe0434352), pid=9708, tid=7756
#
# JRE version: 7.0-b147
# Java VM: Java HotSpot(TM) Client VM (21.0-b17 mixed mode, sharing windows-x86 )
# Problematic frame:
# C  [KERNELBASE.dll+0x812f]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows

1
请查看此链接:https://dev59.com/bWsy5IYBdhLWcg3w-zF4 - ozanonurtek
@phantom,我对使用C++的知识不是很了解。你能帮我学习如何从C++中调用C#函数吗? - MorganM
1
我会尝试,但现在不行,可能需要两个小时。 - ozanonurtek
我会很高兴,我已经尝试了两天了,但是无法得到解决方案。 - MorganM
看一下这个,https://dev59.com/x3bZa4cB1Zd3GeqPCywo 看起来很容易。 - Low Flying Pelican
显示剩余2条评论
1个回答

3

首先,让我们创建一个如下所示的C#文件:

using System;
public class Test{
  public Test(){}
  public String ping(){
    return "C# is here.";
  }
}

然后使用以下命令进行编译:

csc.exe /target:module Test.cs  

您可以在.NET框架的安装路径中找到csc.exe。之后创建Java文件:

public class Test{
  public native String ping();
  public static void main(String[] args){
    System.load("/path/to/dll");
    System.out.println("Java is running.");
    Test t = new Test();
    System.out.println("Trying to catch C# " + r.ping());
  }
}

javac Test.java会生成Test.class文件。

javah -jni Test会生成Test.h文件,该文件将被包含在C++代码中。

之后,我们需要创建我们的C++文件:

#include "stdafx.h"
#include "JAVA/Test.h"
#include "MCPP/Test.h"
#pragma once
#using <mscorlib.dll>
#using "Test.netmodule"
JNIEXPORT jstring JNICALL Java_Test_ping(JNIEnv *env, jobject obj){
  Test^ t = gcnew Test();
  String^ ping = t->ping();
  char* str = static_cast<char*>((System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(ping)).ToPointer());

  char cap[128];
  strcpy_s(cap, str);

  return env->NewStringUTF(cap);
}

最后:

c:\>java Test

希望这能帮助到您。以下是在Java中使用C#函数的基本示例。
参考来源: https://www.quora.com/How-common-is-the-problem-of-calling-C-methods-from-Java-Do-many-developers-come-across-such-necessity

我已经创建了C#和Java文件并编译成功,但问题出在C++的这一部分,我应该在哪里包含它 #using "Test.netmodule"。我正在使用Visual Studio 2013。 - MorganM
仍然出现这个错误 #Java运行时环境检测到一个致命错误: #内部错误(0xe0434352),pid = 5800,tid = 5792 #JRE版本:7.0-b147 #Java虚拟机:Java HotSpot(TM)客户端VM(21.0-b17混合模式,共享windows-x86) #有问题的帧: #C [KERNELBASE.dll+0x812f] #无法写入核心转储。在Windows客户端版本中,默认情况下未启用小型转储 #具有更多信息的错误报告文件已保存为: - MorganM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接