C Pointers in C#
-
Hi guys, I'm writing a SQLite wrapper but I'm having trouble handling pointers. Example: Original C function (from SQLite doc): const char *sqlite3_column_name(sqlite3_stmt*, int N); Import in C#: [DllImport("sqlite3.dll", EntryPoint = "sqlite3_column_name")] private static extern string sqlite3_column_name(IntPtr sqlite3_stmt, int N); This works, but sometimes (I dont understand why yet) it gives me back an Access Violation Exception. The same happens with this: const char *sqlite3_libversion(void); [DllImport("sqlite3.dll", EntryPoint = "sqlite3_libversion")] private static extern string sqlite3_libversion(); That always raise an Access Violation Excpetion. What I'm doing wrong? Thank everyone in advance. -MR
-
Hi guys, I'm writing a SQLite wrapper but I'm having trouble handling pointers. Example: Original C function (from SQLite doc): const char *sqlite3_column_name(sqlite3_stmt*, int N); Import in C#: [DllImport("sqlite3.dll", EntryPoint = "sqlite3_column_name")] private static extern string sqlite3_column_name(IntPtr sqlite3_stmt, int N); This works, but sometimes (I dont understand why yet) it gives me back an Access Violation Exception. The same happens with this: const char *sqlite3_libversion(void); [DllImport("sqlite3.dll", EntryPoint = "sqlite3_libversion")] private static extern string sqlite3_libversion(); That always raise an Access Violation Excpetion. What I'm doing wrong? Thank everyone in advance. -MR
Wouldn't it be better to just use http://sqlite.phxsoftware.com/[^]
-
Wouldn't it be better to just use http://sqlite.phxsoftware.com/[^]
-
Hi guys, I'm writing a SQLite wrapper but I'm having trouble handling pointers. Example: Original C function (from SQLite doc): const char *sqlite3_column_name(sqlite3_stmt*, int N); Import in C#: [DllImport("sqlite3.dll", EntryPoint = "sqlite3_column_name")] private static extern string sqlite3_column_name(IntPtr sqlite3_stmt, int N); This works, but sometimes (I dont understand why yet) it gives me back an Access Violation Exception. The same happens with this: const char *sqlite3_libversion(void); [DllImport("sqlite3.dll", EntryPoint = "sqlite3_libversion")] private static extern string sqlite3_libversion(); That always raise an Access Violation Excpetion. What I'm doing wrong? Thank everyone in advance. -MR
Hi, Maybe your problem is connected with string marshalling. Native functions returns char* strings - 1 byte per letter, as far as I know, c# automatically tries to marshal strings as unicode charaters (2B per letter), try maybe such code:
[DllImport("sqlite3.dll", EntryPoint = "sqlite3_libversion", CharSet=CharSet.Ansi)] private static extern string sqlite3_libversion();
Alternatively you could also try using this attribute:[return:MarshalAs(UnmanagedType.LPStr)]
-
Yep, but since I'm quite new to C# I would like to make one myself, for practicing in making wrappers for DLLs. My question is more about pointers to Char and strings than about SQLite. Btw Thank you, I'll check that asap :)
In that case you can download source code of sqlite wrapper and research the code.
Giorgi Dalakishvili #region signature My Articles Asynchronous Registry Notification Using Strongly-typed WMI Classes in .NET [^] My blog #endregion
-
Hi, Maybe your problem is connected with string marshalling. Native functions returns char* strings - 1 byte per letter, as far as I know, c# automatically tries to marshal strings as unicode charaters (2B per letter), try maybe such code:
[DllImport("sqlite3.dll", EntryPoint = "sqlite3_libversion", CharSet=CharSet.Ansi)] private static extern string sqlite3_libversion();
Alternatively you could also try using this attribute:[return:MarshalAs(UnmanagedType.LPStr)]
Thank you for your reply, unfortunately I had no luck with your tips. Googling I found a solution, even if it seems a workaround to me instead a properly solution. [DllImport("kernel32")] private extern static int lstrlen(IntPtr str); String PointerToString(IntPtr pointer) { Encoding enc = Encoding.UTF8; int pLen = 0; if (pointer == IntPtr.Zero) pLen = 0; else pLen = lstrlen(ptr); Byte[] bytes = new Byte[pLen]; Marshal.Copy(pointer, bytes, 0, pLen); return enc.GetString(bytes, 0, pLen); }
-
Thank you for your reply, unfortunately I had no luck with your tips. Googling I found a solution, even if it seems a workaround to me instead a properly solution. [DllImport("kernel32")] private extern static int lstrlen(IntPtr str); String PointerToString(IntPtr pointer) { Encoding enc = Encoding.UTF8; int pLen = 0; if (pointer == IntPtr.Zero) pLen = 0; else pLen = lstrlen(ptr); Byte[] bytes = new Byte[pLen]; Marshal.Copy(pointer, bytes, 0, pLen); return enc.GetString(bytes, 0, pLen); }
Hi, I've checked my solution on functions that return ascii strings and unicode strings, and those attributes work pretty well, so maybe the problem is somewhere else? Btw in function you are using, you have utf8 encoding, but you assume that strings are 1B per letter, which is not always true for utf8.
-
Hi, I've checked my solution on functions that return ascii strings and unicode strings, and those attributes work pretty well, so maybe the problem is somewhere else? Btw in function you are using, you have utf8 encoding, but you assume that strings are 1B per letter, which is not always true for utf8.
I tryed to sort out the problem so I made this public partial class Form1 : Form { [DllImport("sqlite3.dll", EntryPoint = "sqlite3_libversion",CharSet=CharSet.Ansi)] private static extern string sqlite3_libversion(); [return: MarshalAs(UnmanagedType.LPStr)] public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { sqlite3_libversion(); } } Kept it simplier as possible. This should return a string with the version of sqlite. But this always gives the Accession Violation Exception. You can easily try this downloading the sqlite3.dll from the official site. Thank for you help :) I really appreciate.
-
I tryed to sort out the problem so I made this public partial class Form1 : Form { [DllImport("sqlite3.dll", EntryPoint = "sqlite3_libversion",CharSet=CharSet.Ansi)] private static extern string sqlite3_libversion(); [return: MarshalAs(UnmanagedType.LPStr)] public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { sqlite3_libversion(); } } Kept it simplier as possible. This should return a string with the version of sqlite. But this always gives the Accession Violation Exception. You can easily try this downloading the sqlite3.dll from the official site. Thank for you help :) I really appreciate.
Hi, This code should work flawlessly, I've tried it on the newest library. Program prints "3.6.7"
public class Program
{
[DllImport("sqlite3.dll")]
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string sqlite3_libversion();public unsafe static void Main()
{
Console.WriteLine(sqlite3_libversion());
}
}Few hints: 1. If you want to bind attribute to function, you have to place function under [] tags. 2. EntryPoint has to be given if c# function name differs from function declared in native dll
-
Hi, This code should work flawlessly, I've tried it on the newest library. Program prints "3.6.7"
public class Program
{
[DllImport("sqlite3.dll")]
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string sqlite3_libversion();public unsafe static void Main()
{
Console.WriteLine(sqlite3_libversion());
}
}Few hints: 1. If you want to bind attribute to function, you have to place function under [] tags. 2. EntryPoint has to be given if c# function name differs from function declared in native dll