go - 在 C 共享库中公开一个带有 2D slice 作为参数的函数(通过 JNA 和 C 在 Java 中使用)

标签 go shared-libraries

我正在尝试使用 go 编写一个简单的矩阵运算 API,并将 API 公开为共享库。这个共享库将从 Java(使用 JNA)和 C 中使用。 关于使用除简单 intstring 之外的任何数据类型作为函数参数的文档非常少。 我的要求是将具有 1 个或多个 2D slice 的函数作为参数和返回类型公开。我无法弄清楚是否支持这样的事情。 这可能吗?有这方面的例子吗?

最佳答案

我认为关键点是查看go build 工具生成的slice、string 和int 的c 绑定(bind)。 2D slice 没试过,不过应该和1D slice 有unsafe pointer converter 没什么区别,也许只是多了一次分配和转换。

我不确定这是最好的方法,但这是一维 slice 的示例:

开始部分:

import "C"
//export CFoo
func CFoo(content []byte) string{
    var ret []byte
    //blablabla to get ret
    cbuf := unsafe.Pointer(C.malloc(C.size_t(len(ret))))
    C.memcpy(cbuf, unsafe.Pointer(&ret[0]), C.size_t(len(ret)))
    var finalString string
    hdr := (*reflect.StringHeader)(unsafe.Pointer(&finalString))
    hdr.Data = uintptr(unsafe.Pointer(cbuf))
    hdr.Len = len(ret)
    return finalString
}

-buildmode=c-shared编译,得到libmygo.so

我不知道JNA,期待它像JNI。 JNI 部分以及纯 C 部分:

#include <stdio.h>
#include <jni.h>
#include <string.h>

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt32 GoInt;
typedef GoUint32 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;

typedef struct { const char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

JNIEXPORT JNICALL jbyteArray Java_com_mynextev_infotainment_app_myev_Native_foo(JNIEnv* env, jobject obj,jbyteArray content){
    JNIEnv ienv = *env;

    void * Ccontent = ienv->GetByteArrayElements(env, content, 0); 
    int Lcontent = ienv->GetArrayLength(env, content);
    GoSlice Gcontent = {Ccontent, Lcontent, Lcontent};
    if(!gret.n){
        printf("jni CDoAESEnc");
        return NULL;
    }
    jbyteArray ret = ienv->NewByteArray(env, gret.n);
    ienv->SetByteArrayRegion(env, ret, 0, gret.n, gret.p);
    free((void*)gret.p);
    ienv->ReleaseByteArrayElements(env, content, Ccontent, JNI_ABORT);
    return ret;
}

使用 libmygo.so 构建它。

最后你得到两个so文件。一个用于 C,可以独立使用;一个用于 Java,必须与 libmygo.so 一起使用。

关于go - 在 C 共享库中公开一个带有 2D slice 作为参数的函数(通过 JNA 和 C 在 Java 中使用),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36687306/

相关文章:

Java 无法在 OSX 上使用 JNI 加载共享对象库

struct - 嵌入式结构方法可以了解父/子吗?

c - 通过环境变量告诉 ld 在哪里查找目录

linux - 链接期间未找到符号

java - 简单的Java游戏引擎/库

c++ - 在共享对象 unix/linux 中查看 c++ 方法/构造函数

asynchronous - 缓冲 channel 的理想大小和工作人员数量是多少?

json - 无效操作 : type interface {} does not support indexing

go - 拆分一串单边字母,单边数字

go - Go 函数中返回变量的个数可变