问题描述
我正在尝试PInvoke具有嵌套结构数组指针的结构参数的方法。 c declaration看起来像这样:
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 example
更新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
正如David在他的回答中所建议的,我将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;
}
解决方法
您错误地翻译了此字段
bool *nullmask
这不是bool
,而是指针。声明为
IntPtr nullmask;
可能还有其他错误,因为我们看不到所有翻译。此外,数组访问指针算法中的+8
看起来很可疑。