JNA如何将String []从Java传递到C代码

docker开发人员:

我有一个问题。我首先需要了解如何传递“ String [] contentsStatic”。我可以在JNA文档中看到String []应该映射到Char **。我不确定如何在Java方面将此映射。在我的特定实现中,我甚至不确定这是否会真正起作用,因为我要使用的C代码是MatLab,因此在C代码中,它期望的是'const emxArray_char_T * contentsStatic。我不知道这是什么。

这是C面:

Initialise(const emxArray_char_T *contentsStatic, const
                    emxArray_char_T *contentsDynamic, int b_phoneAngleDeg, double
                            b_stepCalibrationOffset, int b_initialFloorNumber, int
                            b_initialPointingAngleDeg, int b_initialAlignmentMode, bool *mapStatus, bool
  *paramStatus);

Java方面是:

initialise(String[] contentsStatic,
                                String[] contentsDynamic,
                                int phoneRelativeToBodyDegree,
                                double initialStepCalibrationOffset, 
                                int startingFloorID,
                                LatLng startingLatLong,
                                double startingAccuracy,
                                boolean _CDontActuallyUse,
                                int phoneOrientation,
                                int phoneOrientationUse,
                                boolean magntometerValid
                                )

映射方法供参考:

private struct MatWrap
{
    var MatString: MatString
    private var string_size_array_to_pass: [Int32]
    private var string_bytes_int8: [Int8]

    init(string: String)
    {
        let string_size = MatWrap.getSize(string: string)

        self.string_bytes_int8 = MatWrap.getInt8Array(string: string)
        self.string_size_array_to_pass = MatWrap.getSizeArray(size: string_size)

        self.MatString = MatWrap.makeMatString(
            data: &self.string_bytes_int8,
            size: &self.string_size_array_to_pass,
            allocatedSize: string_size
        )
    }

    private static func getInt8Array(string: String) -> [Int8] {
        let data = string.data(using: .ascii, allowLossyConversion: false)!
        let bytes = [UInt8](data)
        let bytes_int8 = bytes.map{Int8($0)}
        return bytes_int8
    }

    private static func getSize(string: String) -> Int32 {
        return Int32(string.lengthOfBytes(using: .ascii))
    }

    private static func getSizeArray(size: Int32) -> [Int32] {
        return [1, size]
    }

    private static func makeMatString(data: UnsafeMutablePointer<Int8>, size: UnsafeMutablePointer<Int32>, allocatedSize: Int32) -> MatString {
        return MatString(data: data, size: size, allocatedSize: allocatedSize, numDimensions: 1, canFreeData: false)
    }
}

用于准备联接的String []通过的方法:

allFloorsDynamic_wrappedMatString =  MatWrap(string: contentsDynamic.joined())
丹尼尔·威迪斯(Daniel Widdis):

您在问如何传递a,String[]但这不是本机功能所期望的。

查看Matlab文档,它emxArray_char_T是一个结构:

struct emxArray_char_T
{
   char * str;
   int size;
};

此外,在阅读文档时,您可以看到以下关于API的描述:

代码生成器生成C / C ++数组定义,该定义取决于数组元素类型以及数组使用静态还是动态内存分配。数组的两种内存分配需要两种不同的实现:

  • 对于其大小限制在预定义阈值内的数组,生成的C / C ++定义由指向内存的指针和存储数组元素总数(即数组大小)的整数组成。该数组的内存来自程序堆栈,并且是静态分配的。

  • 对于其大小未知且在编译时无界或其边界超过预定义阈值的数组,生成的C / C ++定义由称为emxArray的数据结构组成。创建emxArray时,将根据当前数组大小设置中间存储范围。在程序执行期间,由于超出了中间存储范围,因此生成的代码会从堆中占用额外的内存空间,并将其添加到emxArray存储中。该阵列的内存是动态分配的。

对于将const传递给本机端的情况,可以使用静态分配的版本。但是,这里遇到了JNA的局限性:定义结构时必须知道数组的大小。因此,要使用一种结构,您必须这样做:

@FieldOrder ({"str", "size"})
class emxArray_char_T_3 extends Structure {
    public String[] strArray = new String[3];
    public int size = 3;
}

您将定义它,然后设置3个strArray元素。您可以为不同的大小执行类似的数组。

但是,MATLAB似乎具有用于创建此数组的辅助函数,例如emxCreateWrapper_char_T您可能想弄清楚如何使用它们。

他们说,进一步深入研究文档

如果不使用动态内存分配,则结构中的数组将转换为一维数组,而不是指针。

对于字符串来说,这是一个挑战,字符串是可变长度的数组,String[]其他语言的典型映射将是指向其他地方的字符串的指针数组。这意味着要直接将现有结构与该const类型一起使用,必须为字符串定义恒定长度的字符数组。

查看您在编辑中添加的字符串数组的语法,看起来仍然必须传递单个字符串,但是这种表示法joined意味着它需要某种带分隔符的表示法。同样,这是您必须搜索API才能确切找到分隔符的内容!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章