如何从C+;调用非原语类型作为参数的Java入口点方法+;使用GraalVM

如何从C+;调用非原语类型作为参数的Java入口点方法+;使用GraalVM,java,c++,visual-c++,graalvm,graalvm-native-image,Java,C++,Visual C++,Graalvm,Graalvm Native Image,我正在尝试使用graalvm创建java代码的共享库(带有头文件和库文件的dll) 有一个java方法,它有2个字符串类型的参数,我将从C++调用。 我正在使用一个maven项目,我无法用java代码创建dll,我正在使用graalvm将java代码转换为dll 我的java代码如下所示: package demo; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.c.function.C

我正在尝试使用graalvm创建java代码的共享库(带有头文件和库文件的dll)

有一个java方法,它有2个字符串类型的参数,我将从C++调用。 我正在使用一个maven项目,我无法用java代码创建dll,我正在使用graalvm将java代码转换为dll

我的java代码如下所示:

package demo;

import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.c.function.CEntryPoint;

public class MyClass{
    
    @CEntryPoint (name = "myFunc")
    public static byte[] myfunc(IsolateThread thread, String x, String y) {

        // logic goes here

        byte[] arr = "byte array will contain actual bytes".getBytes();
        
        return arr;
    }
但是当我试图将代码构建到dll中时,我遇到了这个错误

错误:入口点方法参数类型仅限于基元类型、单词类型和枚举(@CEnum):demo.MyClass.myFunc(IsolateThread、String、String)

我搜索了一下,但没有找到解决这个问题的合适方法。 这里有人能告诉我如何用C++调用java方法和非原始数据类型吗?
任何建议都是一个很大的帮助,感谢您提前提出了一个特定的前提条件,java的方法需要在GraalVM中成功地从C或C++中运行。 在设计要用
@CEntryPoint
注释的Java入口点方法时,也应该考虑到这些因素。提到了以下先决条件

  • Java入口点方法只允许包含基本Java类型、字值和枚举。另外,为了实际使用
    Enum
    Enum类必须有
    CEnum
    注释
  • Java入口点方法应该是静态的
  • Java入口点方法应该捕获所有异常,因为它不应该抛出任何异常。如果未捕获到异常,则打印该异常,然后终止进程。然而,
    @CEntryPoint
    文档明确提到捕获java入口点方法内部的所有异常
  • 需要一个
    IsolateThread
    参数。更准确地说
  • 执行上下文必须作为参数传递,并且可以是 特定于当前线程的IsolateThread或Isolate 用于连接当前线程的隔离。这些指针 可通过电流隔离的方法获得。当有更多 如果这些类型中有多个参数,则必须恰好有一个参数 对于IsolateThread,使用CEntryPoint.IsolateThreadContext进行注释, 或用于隔离的CEntryPoint.IsolateContext

    问题中的示例抛出此错误,因为
    myFunc
    方法签名包含对象,例如
    String
    参数。即
    x
    y
    。根据上述前提条件1,这是不允许的。这就是错误描述试图说的

    解决方案是使用提供的功能在Java类型和C类型之间进行转换。在这种情况下,为了在
    C
    Java
    之间传递文本,我们可以使用。由于文本在
    C
    Java
    中的建模方式不同,因此
    Java字符串必须转换为
    C*char
    ,反之亦然

    创建并返回Java字符串

    byte[]
    表示文本时,可以使用下面的示例

    //These are the imports needed
    import org.graalvm.nativeimage.c.type.CCharPointer;
    import org.graalvm.nativeimage.c.type.CTypeConversion;
    
    @CEntryPoint(name = "myFunc")
      public static CCharPointer myFunc(IsolateThread thread, CCharPointer x, CCharPointer y) {
            //Convert C *char to Java String
            final String xString= CTypeConversion.toJavaString(x);
            final String yString= CTypeConversion.toJavaString(y);
    
            //logic goes here
    
            //Convert Java String to C *char
            try(final CTypeConversion.CCharPointerHolder holder=CTypeConversion.toCString("Hello from Java")){
            
                    final CCharPointer result=holder.get();
                    return result;
             }
            
      }
    
    使用并返回在C中分配的数组

    您还可以遵循C风格,将C中的数组作为参数传递,然后使用此数组在Java中写入结果字节值。该方法可以将
    Java字节
    值写入
    *char
    char[]
    中的特定数组索引。如果需要,还可以返回字节数组

    @CEntryPoint(name = "myFunc2")
      public static CCharPointer myFunc2(IsolateThread thread
             , CCharPointer x, CCharPointer y                                                                                  
             , CCharPointer resultArray, int resultArrayLength) {
    
            //Convert C *char to Java String
            final String xString= CTypeConversion.toJavaString(x);
            final String yString= CTypeConversion.toJavaString(y);
    
            //logic goes here
    
            //Fill in the result array
            final byte sampleByteValue=7;
            for(int index =0; index<resultArrayLength; index++){
            resultArray.write(index, sampleByteValue);
            }
            return resultArray;
      }
    
    @CEntryPoint(name=“myFunc2”)
    公共静态CCharPointer myFunc2(IsolateThread线程
    ,CCharPointer x,CCharPointer y
    ,CCharPointer结果数组,int结果数组长度){
    //将C*字符转换为Java字符串
    最终字符串xString=CTypeConversion.toJavaString(x);
    最终字符串yString=CTypeConversion.toJavaString(y);
    //逻辑就在这里
    //填写结果数组
    最终字节sampleByteValue=7;
    
    对于(int index=0;index x1),非常感谢,我了解java和C++之间字符串类型的转换。将不包含文本它将只包含字节,它是否也适用于此?不客气。是的,我将更新我的答案,以包括一个示例。我的字节数组将是巨大的,我可以一次性写入整个字节数组,还是只需在特定索引处写入它?使用NIO字节缓冲区本身就是一个主题,可能是另一个问题因为NIO是独立于GraalVM的东西。你可以在一个新问题中尝试一些东西,如果可能的话,我可以提供帮助。例如,在这里传递对象是不可能的,正如我的答案和javadoc中的前提条件1所述,你能得到的最接近的是使用一种独立的格式,例如JSON和封送/解封送。您好r答案有效,我的编码类型有问题。实际上,我需要一个base64编码的字符串,但我不知道CTypeConversion使用什么编码,因为我无法使用base64解码器将其解码为字节数组,你能帮我吗?