編譯我的marshalling helloworld question,我遇到了將C中分配的數組編碼爲C#的問題。我花了好幾個小時來研究可能會出錯的地方,但是我試過的所有結果都出現了錯誤,例如AccessViolationException。在C#中編組C的數組 - 簡單的HelloWorld
處理在C中創建數組的函數如下。
__declspec(dllexport) int __cdecl import_csv(char *path, struct human ***persons, int *numPersons)
{
int res;
FILE *csv;
char line[1024];
struct human **humans;
csv = fopen(path, "r");
if (csv == NULL) {
return errno;
}
*numPersons = 0; // init to sane value
/*
* All I'm trying to do for now is get more than one working.
* Starting with 2 seems reasonable. My test CSV file only has 2 lines.
*/
humans = calloc(2, sizeof(struct human *));
if (humans == NULL)
return ENOMEM;
while (fgets(line, 1024, csv)) {
char *tmp = strdup(line);
struct human *person;
humans[*numPersons] = calloc(1, sizeof(*person));
person = humans[*numPersons]; // easier to work with
if (person == NULL) {
return ENOMEM;
}
person->contact = calloc(1, sizeof(*(person->contact)));
if (person->contact == NULL) {
return ENOMEM;
}
res = parse_human(line, person);
if (res != 0) {
return res;
}
(*numPersons)++;
}
(*persons) = humans;
fclose(csv);
return 0;
}
的C#代碼:
IntPtr humansPtr = IntPtr.Zero;
int numHumans = 0;
HelloLibrary.import_csv(args[0], ref humansPtr, ref numHumans);
HelloLibrary.human[] humans = new HelloLibrary.human[numHumans];
IntPtr[] ptrs = new IntPtr[numHumans];
IntPtr aIndex = (IntPtr)Marshal.PtrToStructure(humansPtr, typeof(IntPtr));
// Populate the array of IntPtr
for (int i = 0; i < numHumans; i++)
{
ptrs[i] = new IntPtr(aIndex.ToInt64() +
(Marshal.SizeOf(typeof(IntPtr)) * i));
}
// Marshal the array of human structs
for (int i = 0; i < numHumans; i++)
{
humans[i] = (HelloLibrary.human)Marshal.PtrToStructure(
ptrs[i],
typeof(HelloLibrary.human));
}
// Use the marshalled data
foreach (HelloLibrary.human human in humans)
{
Console.WriteLine("first:'{0}'", human.first);
Console.WriteLine("last:'{0}'", human.last);
HelloLibrary.contact_info contact = (HelloLibrary.contact_info)Marshal.
PtrToStructure(human.contact, typeof(HelloLibrary.contact_info));
Console.WriteLine("cell:'{0}'", contact.cell);
Console.WriteLine("home:'{0}'", contact.home);
}
第一human struct
被編組的罰款。我在第一個之後得到訪問衝突異常。我覺得我錯過了一些內部結構指針編組結構的東西。我希望我可以忽略一些簡單的錯誤。你看到這段代碼有什麼問題嗎?
查看完整源代域這個GitHub gist。
謝謝!我正在編寫這樣的代碼,因爲我需要它跨平臺運行。 C代碼是一個將在嵌入式和桌面Linux以及Windows上運行的庫。我在Linux上提供了一個CLI,但Windows需要一個GUI,我更喜歡在Windows上爲GUI編寫C#。 我在C#中使用C代碼相當新,所以我不知道所有的最佳實踐。這是我的實際代碼的一個簡單化的例子,我提供了一個函數來釋放C中分配的內存。 –