Goeiemiddag,
Ik probeer via PInvoke een Win32-dll te gebruiken (die van SQLite). Een van de functies op die DLL retourneert een resultset door voor elke rij een callback functie aan te roepen. Nu is het vreemde dat alles het 'even' goed doet, en daarna niet meer: voor de eerste 3 rijen krijg ik gewoon de verwachte resultaten terug, en vervolgens krijg ik een NullReferenceException om m'n oren. Wat nog vreemder is, is dat deze exception niet gebeurt in mijn callback-implementatie, maar echt in de 'native' code van de Exec()-methode.
Kan iemand me misschien een suggestie doen van wat hier foutgaat?
De definities van mijn callback-delegate en de native functie die deze delegate gaat gebruiken zien er als volgt uit:
Nu, het aanroepen van deze native functie gaat als volgt:
Dit levert 3 van de 5 resultaten correct op, en vervolgens krijg ik een NullReferenceException op de call naar SQLiteInterop.Exec() op regel 5
Wie heeft ideen?
Ik probeer via PInvoke een Win32-dll te gebruiken (die van SQLite). Een van de functies op die DLL retourneert een resultset door voor elke rij een callback functie aan te roepen. Nu is het vreemde dat alles het 'even' goed doet, en daarna niet meer: voor de eerste 3 rijen krijg ik gewoon de verwachte resultaten terug, en vervolgens krijg ik een NullReferenceException om m'n oren. Wat nog vreemder is, is dat deze exception niet gebeurt in mijn callback-implementatie, maar echt in de 'native' code van de Exec()-methode.
Kan iemand me misschien een suggestie doen van wat hier foutgaat?
De definities van mijn callback-delegate en de native functie die deze delegate gaat gebruiken zien er als volgt uit:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| /// <summary> /// Defines the method signature that should be passed as a callback function /// to <see cref="SQLiteInterop.Exec"/>. If this callback function returns a /// non-zero value then the query is aborted. /// Its C prototype is: int callbackFn(void*, int, char**,char**) /// </summary> public delegate int ExecCallbackDlg(IntPtr customArg, int nrOfColumns, IntPtr pColValues, IntPtr pColNames); /// <summary> /// Executes a SQL statement against an opened SQLite database and returns /// each row of the resultset through a callback function. Its C prototype is: /// int sqlite3_exec(sqlite3*, const char *, int (*callback)(void*,int,char**,char**), void *, char **) /// </summary> [DllImport("..\\..\\sqlite3.dll", EntryPoint = "sqlite3_exec", CharSet=CharSet.Ansi)] public static extern int Exec(IntPtr sqlDB, string sqlStatement, ExecCallbackDlg callback, IntPtr customArg, ref IntPtr pErrorMsg); |
Nu, het aanroepen van deze native functie gaat als volgt:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| public static void Test(IntPtr pDB) { IntPtr pErrorMsg = IntPtr.Zero; string sqlStatement = "select ID, Title from MyTable limit 5"; int result = SQLiteInterop.Exec(pDB, sqlStatement, new ExecCallbackDlg(ExecCallback), IntPtr.Zero, ref pErrorMsg); } //Matches the signature for ExecCallbackDlg public static int ExecCallback(IntPtr customArg, int nrOfColumns, IntPtr pColValues, IntPtr pColNames) { try { string colName, colValue; IntPtr stringPtr; Console.WriteLine("Returned row:"); //Unmarshal the string arrays. for(int index = 0; index < nrOfColumns; index++) { stringPtr = Marshal.ReadIntPtr(pColNames, index * 4); colName = Marshal.PtrToStringAnsi(stringPtr); stringPtr = Marshal.ReadIntPtr(pColValues, index * 4); colValue = Marshal.PtrToStringAnsi(stringPtr); Console.WriteLine("[{0}] = \"{1}\"", colName, colValue); } } catch(Exception ex) { Console.WriteLine("Exception occured: " + ex); } return 0; } |
Dit levert 3 van de 5 resultaten correct op, en vervolgens krijg ik een NullReferenceException op de call naar SQLiteInterop.Exec() op regel 5
Wie heeft ideen?