[英]Debugging DLLImport in C#
在過去的12個小時左右的時間里,我一直在嘗試讓MySQL嵌入式庫在我的C#應用程序中運行,並且已經停滯了很長時間。 調用mysql_server_init()
時出現以下錯誤...
未處理的異常:System.AcessViolationException:嘗試讀取或寫入受保護的內存。
C ++方法采用一個int
和兩個char**
作為參數,但是有人告訴我,以空終止的string[]
數組在C#中就足夠了。 由於這是您應該調用的第一種方法,因此我對此問題有些茫然。
這是我的代碼......
public class MySQLServer
{
[DllImport("libmysqld.dll")]
static extern int mysql_server_init(int argc, string[] argv, string[] groups);
[DllImport("libmysqld.dll")]
static extern void mysql_server_end();
public static bool Start()
{
string[] argv = new string[3];
argv[0] = "mysql_test";
argv[1] = "--datadir=C:/MYSQLTEST";
argv[2] = null;
string[] groups = new string[3];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";
groups[2] = null;
int res;
if ((res = mysql_server_init(3, argv, groups)) == 1)
{
Console.WriteLine("MySQL Library Init Failed with error code: %d", res);
return false;
}
Console.WriteLine("MySQL Library Started Successfully!");
return true;
}
}
如果正在讀取字符串,您應該能夠作為字符串數組傳遞。
如果要編寫它們,則必須將參數聲明為IntPtrs
,為它們分配內存,然后自己編組數據(此外,您還需要IntPtrs
分配內存)。
如果您這樣調用會發生什么情況(argc:= 2):
if ((res = mysql_server_init(2, argv, groups)) == 1)
{
Console.WriteLine("MySQL Library Init Failed with error code: %d", res);
return false;
}
在我看來,你有一個小錯誤,導致mysql_server_init
讀取超出數組邊界。 將3
替換為2
並刪除第三個數組條目。 默認封送程序將完成剩下的工作。
public static bool Start()
{
string[] argv = new string[3];
argv[0] = "mysql_test";
argv[1] = "--datadir=C:/MYSQLTEST";
string[] groups = new string[3];
groups[0] = "libmysqd_server";
groups[1] = "libmysqd_client";
int res;
if ((res = mysql_server_init(2, argv, groups)) == 1)
{
Console.WriteLine("MySQL Library Init Failed with error code: %d", res);
return false;
}
}
在此線程中 ,您根本不應使用mysql_server_init
,而應使用mysql_library_init
:
- “ argv”和“ groups”都由庫存儲並在以后使用。 這是一個嚴重的問題,因為如果使用P / Invoke封送處理,則函數返回后,.NET傳遞給該函數的指針將變得無效。 當庫稍后嘗試引用argv或組時,除了在那里,它什么也找不到,這會導致意外行為或崩潰。
如果您使用的是MySQL 5.0.3或更高版本,請嘗試使用mysql_library_init - 它會生成argv和groups的內部副本,因此您可以毫無困難地繼續使用P / Invoke編組(只要您向其添加空條目)組末尾)。 否則,您必須為數組和每個字符串自己分配內存,以確保只要程序正在運行,指針就保持有效。
所以,如果你可以切換到使用mysql_library_init
,我建議這樣做。 副手編組不是一項微不足道的工作(但也不是太難)。
C ++方法采用一個int和兩個char **作為參數,但是有人告訴我,以空終止的string []數組在C#中就足夠了。 由於這是您應該調用的第一種方法,因此我對該問題有些茫然。
到底是誰告訴你的?
我確實相信您可以使用對char []的引用
[DllImport(“libmysqld.dll”)] static extern int mysql_server_init(int argc,ref char [] argv,ref char [] groups);
確保調用約定匹配否則您將遇到問題。
米奇·惠特(Mitch Wheat)的答案可以通過以下線程來增強: 在C#中編組char **
一些附加信息: C#編組char **和unsigned char **
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.