繁体   English   中英

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

[英]JNA how to pass String[] from Java to C code

我有一个问题。 我首先需要了解如何传递“String[] contentsStatic”。 我可以在 JNA 文档中看到 String[] 应该是 map 到 Char**。 我不确定如何在 Java 端使用 map。 在我的特定实现中,我什至不确定这是否真的有效,因为我尝试使用的 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())

您在询问如何传递String[]但这不是本机 function 所期望的。

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

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

此外,阅读文档,您可以看到 API 的描述:

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

  • 对于大小在预定义阈值范围内的数组,生成的 C/C++ 定义包含指向 memory 的指针和存储数组元素总数(数组大小)的 integer。 该数组的 memory 来自程序堆栈,是静态分配的。

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

对于将const值传递给本机端的情况,您可以使用静态分配的版本。 但是,在这里您会遇到 JNA 的限制:定义结构时必须知道 arrays 的大小。 所以要使用一个结构,你必须这样做:

@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 您可能想弄清楚如何使用它们。

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

如果您不使用动态 memory 分配,则结构中的 arrays 将转换为一维 arrays,而不是指针。

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

查看您在编辑中添加的字符串 arrays 的语法,看起来您仍然必须传递单个字符串,但joined的符号意味着它需要某种分隔符号。 同样,您必须搜索 API 才能准确找到分隔符!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM