繁体   English   中英

在C#中调试DLLImport

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

  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(“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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM