Структура PInvoke с вложенным массивом структур
Я пытаюсь вызвать метод PInvoke, который имеет параметр структуры с указателем вложенного массива структуры. С заявлением выглядит следующим образом:
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;
}
1 ответ
Вы неправильно перевели это поле
bool *nullmask
Это не
bool
это указатель. Объявите это как
IntPtr nullmask;
Могут быть и другие ошибки, потому что мы не видим все переводы. Кроме того,
+8
в вашем массиве арифметика указателя доступа выглядит подозрительно.