Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[C#] PInvoke en native callbacks: NullReferenceException?

Pagina: 1
Acties:
  • 179 views sinds 30-01-2008
  • Reageer

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
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:
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?

  • igmar
  • Registratie: April 2000
  • Laatst online: 24-11 12:26

igmar

ISO20022

En je weet zeker dat je ook > 3 rows terug krijgt ? De limit is een maximum tenslotte, geen minimum.

  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Je kunt dit denk ik het makkelijkste testen door even een C++ programmatje te schrijven die dezelfde argumenten mee geeft, dan kun je namelijk uitsluiten dat het in de .Net code ligt.

Nu met Land Rover Series 3 en Defender 90


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 31-10 11:58
Heb verder nog nooit iets met SQLite gedaan, maar kan je niet beter kijken naar een provider ipv met P/Invoke te werken?

Vond bijvoorbeeld deze: http://sourceforge.net/projects/sqlite-dotnet2

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Bedankt voor alle feedback tot zover :)
Heb verder nog nooit iets met SQLite gedaan, maar kan je niet beter kijken naar een provider ipv met P/Invoke te werken?

Vond bijvoorbeeld deze: http://sourceforge.net/projects/sqlite-dotnet2
Die had ik ook al gevonden ja ;) Maar het gaat me eigenlijk meer om wat ervaring op te doen met PInvoke in plaats van een kant-en-klare oplossing te gebruiken.
En je weet zeker dat je ook > 3 rows terug krijgt ? De limit is een maximum tenslotte, geen minimum.
Er staan ong. 50 rijen in die tabel, dus ik zou er wel meer dan 3 moeten terugkrijgen. En sowiezo geen NullReferenceException, zelfs als het er maar 3 waren.
Je kunt dit denk ik het makkelijkste testen door even een C++ programmatje te schrijven die dezelfde argumenten mee geeft, dan kun je namelijk uitsluiten dat het in de .Net code ligt.
Nou, waar het tot dusver op lijkt is dat er een NullReferenceException
• vanuit de Interop-code wordt gethrowd (dus de .NET Framework-code die ervoor zorgt dat mijn call begrepen wordt door de Win32-dll, en de callback terugmarshalled naar managed code.
• er in de Win32 dll een null pointer exception optreed, en dat deze vervolgens als NullReferenceException naar managed code wordt gemarshalled en gethrowd.

Weet iemand of het .NET framework dit kan (en doet): Native fouten marshallen als .NET Exceptions?