sto chiamando una funzione di DLL C e la necessità di fornire le seguenti struct C:Marshalling array di stringhe a char ** in C#
typedef struct
{
char *mTableId;
char **mFieldNames;
int mNumFields;
char *mFilter;
char *mSort;
int mOffset;
int mMaxRecords;
char *mTargetRecordFilter;
int mSurroundingRecordsCount;
int *mOwnerIds;
int mNumOwnerIds;
gsi_bool mCacheFlag;
} SAKESearchForRecordsInput;
Il problema è con char ** mFieldNames; Ho provato a smistamento automatico in questo modo:
[MarshalAs (UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPTStr, SizeConst = 9)] [] mFieldNames public String;
In questo modo viene visualizzato un errore in Marshal.SizeOf(): non è possibile calcolare la dimensione corretta. Quindi ho deciso di gestire manualmente i puntatori. In realtà è solo un puntatore alla serie di stringhe C. Ecco il mio codice che sta portando a
System.AccessViolationException: Tentativo di leggere o scrivere memoria protetta. Questo è spesso un'indicazione che un'altra memoria è corrotta.
Quindi ho rovinato i puntatori da qualche parte. Il codice mi sembra OK, dov'è l'errore?
C#:
[StructLayout(LayoutKind.Sequential)]
unsafe public class SAKESearchForRecordsInput {
[MarshalAs(UnmanagedType.LPTStr)]
public String mTableId;
//[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPTStr, SizeConst = 9)] // HARDCODED!?!
//public String[] mFieldNames; // char **mFieldNames;
public IntPtr mFieldNames;
public int mNumFields;
[MarshalAs(UnmanagedType.LPTStr)]
public String mFilter;
[MarshalAs(UnmanagedType.LPTStr)]
public String mSort;
public int mOffset;
public int mMaxRecords;
//[MarshalAs(UnmanagedType.LPTStr)]
public IntPtr mTargetRecordFilter;
public int mSurroundingRecordsCount;
public IntPtr mOwnerIds;
public int mNumOwnerIds;
public gsi_bool mCacheFlag;
}
[DllImport("saketestd.dll")]
unsafe static extern void* sakeSearchForRecords(
IntPtr sake,
IntPtr input, //SAKESearchForRecordsInput *
SAKERequestCallback callback, //SAKERequestCallback
IntPtr userData);
unsafe public bool sakeSearchForRecordsE() {
bool ret = false;
try {
searchInput.mTableId = "bbdx_score";
//searchInput.mFieldNames = mFieldNames.to;
searchInput.mFilter = "num_ratings = 0 AND filestore > 0";
searchInput.mSort = "";
searchInput.mOffset = 0;
searchInput.mMaxRecords = 1;
//searchInput.mTargetRecordFilter = "";
searchInput.mSurroundingRecordsCount = 0;
searchInput.mOwnerIds = IntPtr.Zero;
searchInput.mNumOwnerIds = 0;
searchInput.mCacheFlag = true;
int sakeSize = Marshal.SizeOf(sake);
debug.AddLine(this.getMethodName() + ": sizeof(sake): " + sakeSize);
IntPtr pSake = Marshal.AllocHGlobal(sakeSize);
Marshal.StructureToPtr(sake, pSake, true);
int inputSize = Marshal.SizeOf(searchInput);
debug.AddLine(this.getMethodName() + ": sizeof(input): " + inputSize);
IntPtr pInput = Marshal.AllocHGlobal(inputSize);
Marshal.StructureToPtr(searchInput, pInput, true);
IntPtr[] mFieldNamesPtr;
int i;
if (true) { // IntPtr[]
mFieldNamesPtr = new IntPtr[mFieldNames.Length];
i = 0;
foreach (string str in mFieldNames) {
mFieldNamesPtr[i++] = Marshal.StringToHGlobalAnsi(str);
}
//searchInput.mFieldNames = mFieldNamesPtr;
} else {
//searchInput.mFieldNames = mFieldNames;
}
searchInput.mNumFields = mFieldNames.Length;
void* pRequestInternal = null;
void* p = mFieldNamesPtr[0].ToPointer();
searchInput.mFieldNames = (IntPtr)p;
pRequestInternal = sakeSearchForRecords(
pSake,
pInput,
new SAKERequestCallback(this.sakeSearchForRecordsCB),
IntPtr.Zero
);
sake = (SAKEInternal)Marshal.PtrToStructure(pSake, typeof(SAKEInternal));
if (searchRequest == null) {
debug.AddLine(this.getMethodName() + ": mStartRequestResult: " + sake.mStartRequestResult);
} else {
ret = true;
this.searchRequest = (SAKERequestInternal)Marshal.PtrToStructure(
new IntPtr(pRequestInternal),
typeof(SAKERequestInternal)
);
searchInput = (SAKESearchForRecordsInput)Marshal.PtrToStructure(
pInput,
typeof(SAKESearchForRecordsInput)
);
if (true) {
i = 0;
foreach (string str in mFieldNames) {
Marshal.FreeHGlobal(mFieldNamesPtr[i++]);
}
}
PrintStruct ps = new PrintStruct(sake);
debug.AddLine(this.getMethodName() + ": sake: " + ps);
ps = new PrintStruct(searchRequest);
debug.AddLine(this.getMethodName() + ": searchRequest: " + ps.print_r());
ps = new PrintStruct(searchInput);
debug.AddLine(this.getMethodName() + ": searchInput: " + ps.print_r());
}
Marshal.FreeHGlobal(pSake);
Marshal.FreeHGlobal(pInput);
} catch (Exception ex) {
debug.Text += ex.ToString();
}
return ret;
}
Aggiornamento: si rompe in sakeSearchForRecords(); – Slawa