尝试使用外部库中的方法时出现 Read/Write 访问错误

Getting Read/Write access error when trying to use method from external library

我正在尝试使用库中的以下实现

C++

int CALLBACK xCallback(long xmitlen, int buflen, char *buf, long flen)
{
    return 0;
}

extern "C"  __declspec(dllexport) int __stdcall TXFIlestransfer(int port, string fileName);

__declspec(dllexport) int __stdcall TXFIlestransfer(int port, string fileName)
{
     int ret;

     char *test = &fileName[0];

     ret = sio_FtKermitTx(port, test, xCallback, 27);

     return ret;
}

我正在导入它以与 C# 一起使用并得到 System.AccessViolationException:'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

如能帮助解决此错误,我们将不胜感激。

我通过在我的 C++ dll (Mydll.dll) 中模拟 sio_FtKermitTx 函数来测试你的程序:

int sio_FtKermitTx (int port, char *fname, int (CALLBACK *func) (long xmitlen, int buflen, char *buf, long flen), int key)
{
    return 5;
}

即使是空的body,我也遇到了和你一样的问题

经过多次调查,我注意到问题出在我们在 C#C++ 代码之间使用了 string object 代码,出于一个原因或另一个(例如 unicode / 多字节配置,或者仅仅是因为难以实现共享复杂的 objects)导致问题。

解法:
通过将 string object 替换为原始 char 类型,一切正常:

C#代码:

using System.Runtime.InteropServices;
namespace MyProgramme
{
    class Test
    {
        // Import C++ DLL
        [DllImport("Mydll.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int TXFIlestransfer(int i, char[] filename);
        //public static extern int TXFIlestransfer(int i, string filename); // this crash

        static void RunTest(/*LoadFilterEVENTMessage msg*/)
        {
            string c = "ABC";
            char[] char_arr = c.ToCharArray();
            int i = TXFIlestransfer(3, char_arr);
            // int i = TXFIlestransfer(3, c); string version crash

            string s = i.ToString();
            MessageBox.Show(s);
        }

        /* Methods in DLL being used below  */
        public static void Main()
        {
            RunTest();
        }
    };
}

C++ DLL 代码(Mydll.dll):

extern "C" __declspec(dllexport) int TXFIlestransfer(int port, char fileName[])
{
    int ret;
    char *test = &fileName[0];
    ret = sio_FtKermitTx(port, test, xCallback, 27);
    return ret;
}

无论如何,您的 sio_FtKermitTx 函数在参数中接受 char*,因此将您的 TXFIlestransfer 参数从 string 更改为 char[] 没有问题。

结果:
在 运行 C# 程序之后你会得到这个: