在c#中调试DLLImport
本文关键字:DLLImport 调试 | 更新日期: 2023-09-27 18:11:47
在过去的12个小时左右,我一直在尝试让MySQL嵌入式库在我的c#应用程序中工作,并且已经被卡住了相当长的一段时间。当我调用mysql_server_init()
时,我得到以下错误…
Unhandled Exception: System。accessviolationexception:试图读取或者写保护内存
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
,为它们分配内存,然后自己封送数据(另外你还需要取消内存分配)。
如果像这样调用(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(" libmysqlld .dll")] static extern int mysql_server_init(int
ref char[]组
确保调用约定匹配,否则会遇到问题。
Mitch Wheat的回答可以通过这个线程来增强:在c#中编组char**
一些附加信息:c#编组char**和unsigned char**