Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用JNI从Java调用C#方法_Java_C#_Java Native Interface - Fatal编程技术网

使用JNI从Java调用C#方法

使用JNI从Java调用C#方法,java,c#,java-native-interface,Java,C#,Java Native Interface,我试着按照我在这里找到的例子来做,但我无法让它发挥作用。 这是我的Java类 package jniTester; public class JNITester { static { System.load("D:\\\\VisualStudio_Cpp_2017\\SkriptumTeil5\\Debug\\HelloWorldJNI.dll"); } public static native String welcome(String name);

我试着按照我在这里找到的例子来做,但我无法让它发挥作用。 这是我的Java类

package jniTester;
public class JNITester {
    static {
        System.load("D:\\\\VisualStudio_Cpp_2017\\SkriptumTeil5\\Debug\\HelloWorldJNI.dll");
    }

    public static native String welcome(String name);
}
由此,我用javah创建了jniTester.h文件

这是我的C班

由此我创建了HelloWorldJNI.netmodule

这是我的cpp课

#include "stdafx.h"
#include <jni.h>
#include <string>
#include "jniTester.h"
#using "D:\VisualStudio_C#_2017\SkriptumTeil5\HelloWorldJNI\HelloWorldJNI.netmodule"


using namespace std;

JNIEXPORT jstring JNICALL Java_jniTester_JNITester_welcome(JNIEnv *env, jclass thisclass, jstring inJNIStr) {
    // Step 1: Convert the JNI String (jstring) into C-String (char*)
    const char *inCStr = env->GetStringUTFChars(inJNIStr, NULL);
    if (NULL == inCStr) return NULL;

    // Step 2: Convert the C++ string to C-string, then to JNI String (jstring) and return
    //string outCppStr = "Hello " + std::string(inCStr) + ". Greetings from your C++ buddy";
    //env->ReleaseStringUTFChars(inJNIStr, inCStr);  // release resources
    //return env->NewStringUTF(outCppStr.c_str());

    //// Alternate Step 2:
    System::String^ outStr = HelloWorldJNI::HelloWorldJNI::Welcome(gcnew System::String(inCStr));
    env->ReleaseStringUTFChars(inJNIStr, inCStr);  // release resources
    char* converted = static_cast<char*>((System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(outStr)).ToPointer());
    return env->NewStringUTF(converted);
 }

我不是cpp专家,所以我完全不知道。这里出了什么问题?

首先,您需要使用COM接口在C#中创建程序集DLL

然后,您可以创建一个本机(非托管)DLL包装库,可以与JNI一起使用

你可以照这个做

您还可以查看

举个简单的例子:

C#代码Managed.cs

using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: ComVisible(true)] 
[assembly: AssemblyDelaySign(false)] 
[assembly:AssemblyKeyFileAttribute("Managed.snk")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ManagedClassLibrary {

    [Guid("1CE4ECCB-EB78-4A50-8781-444052C7AEAE")]
    [ComVisible(true)]
    public interface IArithmetic {
        int sum(int lsh, int rhs);
        int subtract(int lsh, int rhs);
    }
    [Guid("30F078F9-F161-4112-B61A-B3BD6B63CB4C"), 
        ClassInterface(ClassInterfaceType.None), 
        ComSourceInterfaces(typeof(IArithmetic))
    ]
    [ComVisible(true)]
    public class ArithmeticImpl:IArithmetic {

        public int sum(int lsh, int rhs)
        {
             return lsh + rhs;
        } 
        public int subtract(int lsh, int rhs)
        {
             return lsh - rhs;
        }
    }

}

C++ DLL包装代码dotNETHORIZ.CPP

#include <windows.h>
#include <Objbase.h>

#include <jni.h>

#import "Managed.tlb" named_guids raw_interfaces_only

using namespace Managed;

class DNArithmetic 
{
    DNArithmetic(const DNArithmetic&) = delete;
    DNArithmetic& operator=(const DNArithmetic&) = delete;
private:
    DNArithmetic() noexcept
    {
     mi_.CreateInstance(CLSID_ArithmeticImpl);
    }
public:
    const DNArithmetic* instanse() {
        if(!_co_init) { 
         ::CoInitialize(NULL);
         _co_init = true;
        }
        static DNArithmetic _ret;            
        return &_ret;
    }
    int sum(int lsh, int rhs) const {
        int ret;
        mi_->sum(lsh, rhs, &ret);
        return ret;
    }

    int subtract(int lsh, int rhs) const {
        int ret;
        mi_->subtract(lsh, rhs, &ret);
        return ret;
    }

    ~DNArithmetic() noexcept
    { 
      ::CoUninitialize();           
    }
private:
    IArithmeticPtr mi_;
    static bool _co_init;
};

bool DNArithmetic::_co_init = false;

extern "C" {

    JNIEXPORT jint JNICALL Java_Arithmetic_dotnet_1sum(JNIEnv *evn, jclass clazz, jint lsh, jint rhs)
    {
        return DNArithmetic::instance()->sum(lsh, rhs);
    }

    JNIEXPORT jint JNICALL Java_Arithmetic_dotnet_1subtract(JNIEnv *evn, jclass clazz, jint lsh, jint rhs)
    {
        return DNArithmetic::instance()->subtract(lsh, rhs);
    }

    BOOL WINAPI DllMain(::HMODULE hprocess,::DWORD fdwReason,::LPVOID lpvReserved)
    {
        switch (fdwReason) {
        case DLL_PROCESS_ATTACH:           
            break;
        case DLL_PROCESS_DETACH:                
            break;
        case DLL_THREAD_ATTACH:
           break;
        case DLL_THREAD_DETACH:
           break;
        }
        return TRUE; // successful
    }

}
和一个构建文件build.cmd(用于演示的简单bat文件)


注意:此解决方案仅适用于Windows操作系统。而且在Unix上不适用于Mono

首先,您需要使用COM接口在C#中创建程序集DLL

然后,您可以创建一个本机(非托管)DLL包装库,可以与JNI一起使用

你可以照这个做

您还可以查看

举个简单的例子:

C#代码Managed.cs

using System;
using System.Reflection;
using System.Runtime.InteropServices;

[assembly: ComVisible(true)] 
[assembly: AssemblyDelaySign(false)] 
[assembly:AssemblyKeyFileAttribute("Managed.snk")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ManagedClassLibrary {

    [Guid("1CE4ECCB-EB78-4A50-8781-444052C7AEAE")]
    [ComVisible(true)]
    public interface IArithmetic {
        int sum(int lsh, int rhs);
        int subtract(int lsh, int rhs);
    }
    [Guid("30F078F9-F161-4112-B61A-B3BD6B63CB4C"), 
        ClassInterface(ClassInterfaceType.None), 
        ComSourceInterfaces(typeof(IArithmetic))
    ]
    [ComVisible(true)]
    public class ArithmeticImpl:IArithmetic {

        public int sum(int lsh, int rhs)
        {
             return lsh + rhs;
        } 
        public int subtract(int lsh, int rhs)
        {
             return lsh - rhs;
        }
    }

}

C++ DLL包装代码dotNETHORIZ.CPP

#include <windows.h>
#include <Objbase.h>

#include <jni.h>

#import "Managed.tlb" named_guids raw_interfaces_only

using namespace Managed;

class DNArithmetic 
{
    DNArithmetic(const DNArithmetic&) = delete;
    DNArithmetic& operator=(const DNArithmetic&) = delete;
private:
    DNArithmetic() noexcept
    {
     mi_.CreateInstance(CLSID_ArithmeticImpl);
    }
public:
    const DNArithmetic* instanse() {
        if(!_co_init) { 
         ::CoInitialize(NULL);
         _co_init = true;
        }
        static DNArithmetic _ret;            
        return &_ret;
    }
    int sum(int lsh, int rhs) const {
        int ret;
        mi_->sum(lsh, rhs, &ret);
        return ret;
    }

    int subtract(int lsh, int rhs) const {
        int ret;
        mi_->subtract(lsh, rhs, &ret);
        return ret;
    }

    ~DNArithmetic() noexcept
    { 
      ::CoUninitialize();           
    }
private:
    IArithmeticPtr mi_;
    static bool _co_init;
};

bool DNArithmetic::_co_init = false;

extern "C" {

    JNIEXPORT jint JNICALL Java_Arithmetic_dotnet_1sum(JNIEnv *evn, jclass clazz, jint lsh, jint rhs)
    {
        return DNArithmetic::instance()->sum(lsh, rhs);
    }

    JNIEXPORT jint JNICALL Java_Arithmetic_dotnet_1subtract(JNIEnv *evn, jclass clazz, jint lsh, jint rhs)
    {
        return DNArithmetic::instance()->subtract(lsh, rhs);
    }

    BOOL WINAPI DllMain(::HMODULE hprocess,::DWORD fdwReason,::LPVOID lpvReserved)
    {
        switch (fdwReason) {
        case DLL_PROCESS_ATTACH:           
            break;
        case DLL_PROCESS_DETACH:                
            break;
        case DLL_THREAD_ATTACH:
           break;
        case DLL_THREAD_DETACH:
           break;
        }
        return TRUE; // successful
    }

}
和一个构建文件build.cmd(用于演示的简单bat文件)


注意:此解决方案仅适用于Windows操作系统。而且在Unix上不适用于Mono

在JNI函数实现周围添加
export“C”{/*myJNI函数*/}
。因为你使用C++来包装C语言。还要检查-如何感谢快速回答。但是,我无法使用导出对账单。它会在Visual Studio中生成语法错误检查类库。对不起,我不知道该检查什么,忘了导出“C”之类的东西。首先是
extern
而不是
export
。第二,它必须已经在头中,否则您将无法调用该函数。您是否尝试过在没有参数的情况下调用C#函数?你尝试过一个独立的C++可执行文件吗?这不太可能是JNI问题。在JNI函数实现的周围添加
export“C”{/*myJNI functions*/}
。因为你使用C++来包装C语言。还要检查-如何感谢快速回答。但是,我无法使用导出对账单。它会在Visual Studio中生成语法错误检查类库。对不起,我不知道该检查什么,忘了导出“C”之类的东西。首先是
extern
而不是
export
。第二,它必须已经在头中,否则您将无法调用该函数。您是否尝试过在没有参数的情况下调用C#函数?你尝试过一个独立的C++可执行文件吗?这不太可能是JNI的问题。非常感谢Victor提供了这个详细的示例。但是,我在.cpp文件中有一个编译错误,该文件包含IArithmeticPtr和CLSID_ArithmeticImpl(未知数据类型)。已解决。名称空间的名称是managedHanks,Victor,非常感谢这个详细的示例。但是,我在.cpp文件中有一个编译错误,该文件包含IArithmeticPtr和CLSID_ArithmeticImpl(未知数据类型)。已解决。命名空间的名称是托管的
public class Arithmetic {

    private static native int dotnet_sum(int lsh, int rhs);

    private static native int dotnet_subtract(int lsh, int rhs);

    private Arithmetic() {
        try {
            System.loadLibrary("dotnet_arithmetic.dll");
        } catch (UnsatisfiedLinkError e) {
            throw new IllegalStateException(e);
        }
    }

    private int sum(int lsh, int rhs) {
        return  dotnet_sum(lsh, rhs);
    }

    private int subtract(int lsh, int rhs) {
        return dotnet_subtract(lsh,rhs);
    }

    public static void main(String[] args) {
        System.setProperty("java.library.path", System.getProperty("user.dir") );
        System.out.println("About to call C# functions from Java over the MS COM");
        Arithmetic instance = new Arithmetic();
        System.out.println("C# 1 + 2 = " + instance.sum(1,2) );
        System.out.println("C# 2 - 1 = " + instance.subtract(2,1) );
    }
}
@echo off
rem make sure you have JAVA_HOME system variable set
rem Please set your VS root dir, should be  somewhere in C:\Program Files 
SET VS_HOME= 
echo %VS_HOME%

echo Take Visual studio command line tools
    call %VS_HOME%\VC\Auxiliary\Build\vcvars64.bat

echo Build C# class library
    sn /k Managed.snk
    csc /optimize /target:library /out:Managed.DLL Managed.cs
    RegAsm  Managed.DLL /tlb:Managed.tlb
    gacutil /i Managed.DLL 

echo Build C++ wrapper JNI DLL
    cl /c /nologo /GL /Zl /std:c++latest /I%JAVA_HOME%\include /I%JAVA_HOME%\include\win32 /Fodotnet_arithmetic.obj dotnet_arithmetic.cpp
    link /DLL /LTCG /LIBPATH:%JAVA_HOME%\lib /OUT:dotnet_arithmetic.dll msvcrt.lib kernel32.lib Ole32.lib jvm.lib dotnet_arithmetic.obj

echo Build Java

javac Arithmetic.java

echo Running the Demo

java Arithmetic

pause