[英]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.