在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;
    }
}

在c#中调试DLLImport

如果正在读取字符串,您应该能够作为字符串数组传递。

如果它们被写入,那么你必须将参数声明为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:

  1. '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**