首页 > 解决方案 > 带有嵌套结构数组的 PInvoke 结构

问题描述

我正在尝试 PInvoke 一个具有嵌套结构数组指针的结构参数的方法。c 声明如下所示:

duckdb_state duckdb_query(duckdb_connection connection, const char *query, duckdb_result *out_result);

typedef struct {
    void *data;
    bool *nullmask;
    duckdb_type type;
    char *name;
} duckdb_column;

typedef struct {
    idx_t column_count;
    idx_t row_count;
    duckdb_column *columns;
    char *error_message;
} duckdb_result;

我在 C# 中这样声明它们:

[DllImport("duckdb.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "duckdb_query")]
public static extern DuckdbState DuckdbQuery(IntPtr connection, string query, out DuckdbResult result);

    [StructLayout(LayoutKind.Sequential)]
    public struct DuckdbColumn
    {
        IntPtr data;
        bool nullmask;  
        DuckdbType type;
        string name;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct DuckdbResult
    {
        public long column_count;
        public long row_count;

        public IntPtr columns;
        public string error_message;
    }

但是当我尝试执行查询并读取列时,我没有得到任何有意义的数据:

result = DuckdbQuery(connection, "SELECT * FROM integers", out queryResult);

DuckdbColumn[] columns = new DuckdbColumn[queryResult.column_count];
var queryResultColumns = queryResult.columns;
            
var columnPointer = Marshal.ReadIntPtr(queryResultColumns);
var ptrToStructure = (DuckdbColumn)Marshal.PtrToStructure(columnPointer, typeof(DuckdbColumn));

列数据

我应该如何更改 PInvoke 声明,以便在执行查询后可以读取列?

在以下位置有示例 c 代码:DuckDB c 示例

更新 1

我可以使用以下代码获取列名:

for (int i = 0; i < queryResult.column_count; i++)
{
    var column = (DuckdbColumn)Marshal.PtrToStructure(queryResult.columns + 8 + (Marshal.SizeOf<DuckdbColumn>() + 8) * i, typeof(DuckdbColumn));
    columns[i] = column;
}

type字段仍然说DUCKDB_TYPE_INVALID

在此处输入图像描述 在此处输入图像描述

更新 2

正如大卫在他的回答中所建议的那样,我改为bool nullmask;现在IntPtr nullmask;可以阅读这样的列信息:

for (int i = 0; i < queryResult.column_count; i++)
{
    var column = (DuckdbColumn)Marshal.PtrToStructure(queryResult.columns + Marshal.SizeOf<DuckdbColumn>() * i, typeof(DuckdbColumn));
    columns[i] = column;
}

标签: c#c.netpinvokeduckdb

解决方案


您翻译此字段有误

bool *nullmask

这不是一个bool它是一个指针。将其声明为

IntPtr nullmask;

可能还有其他错误,因为我们看不到所有的翻译。此外,+8您的数组访问指针算法看起来很可疑。


推荐阅读