Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用C#调用C++;dll,有时内存冲突 我有C++代码< /p>的定义 #define TEST_DLL_API extern "C" __declspec(dllexport) TEST_DLL_API void __cdecl create(const char* sString, const char* sNext, int level, char* response ) ; TEST_DLL_API void __cdecl result(const char* sString, char* response) ;_C# - Fatal编程技术网

使用C#调用C++;dll,有时内存冲突 我有C++代码< /p>的定义 #define TEST_DLL_API extern "C" __declspec(dllexport) TEST_DLL_API void __cdecl create(const char* sString, const char* sNext, int level, char* response ) ; TEST_DLL_API void __cdecl result(const char* sString, char* response) ;

使用C#调用C++;dll,有时内存冲突 我有C++代码< /p>的定义 #define TEST_DLL_API extern "C" __declspec(dllexport) TEST_DLL_API void __cdecl create(const char* sString, const char* sNext, int level, char* response ) ; TEST_DLL_API void __cdecl result(const char* sString, char* response) ;,c#,C#,在我的C#代码中的前几次调用中,它工作得很好,但它第五次导致内存冲突 [DllImport("TEST_DLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)] public static extern void create(string sString, string sNext, int level, StringBuilder response)

在我的C#代码中的前几次调用中,它工作得很好,但它第五次导致内存冲突

[DllImport("TEST_DLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)]
public static extern void create(string sString, string sNext, int level, StringBuilder response);

[DllImport("TEST_DLL.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, SetLastError = true)]
public static extern void result(string sString, StringBuilder response);

<>我想这是不是要释放栈内存,但我不知道如何解决它。

首先,忘记C,然后想想如何从另一个C/C++函数调用C++函数。去掉导出内容后,

result()
函数将声明为:

void result( const char* sString, char* response );
那么该函数的实现呢?假设它只是将输入
sString
复制到输出
响应
字符串。可能代码如下所示:

void result( const char* sString, char* response ) {
    strcpy( response, sString );
}
#define elementsof( array )  ( sizeof(array) / sizeof((array)[0]) )
// ...
char buffer[10];
result( "This is my input string", buffer, elementsof(buffer) );
甜蜜而简单,对吗

好,现在让我们调用这个函数

char buffer[10];
result( "This is my input string", buffer );
你认为这里可能有问题吗<代码>缓冲区长度仅为10个字符,但输入字符串为24个字符,包括终止null

因此,
result()
函数将把24个字符复制到10个字符的缓冲区中。哎呀

事实上,
result()
函数如何知道
响应
缓冲区中有多少可用空间?它没有办法知道这一点

要使函数在C/C++中可用,还必须传入最大缓冲区长度,然后
result()
可以使用该长度限制它复制的内容的长度。它可以通过使用
strcpy\u s()
而不是
strcpy()

你可以这样称呼它:

void result( const char* sString, char* response ) {
    strcpy( response, sString );
}
#define elementsof( array )  ( sizeof(array) / sizeof((array)[0]) )
// ...
char buffer[10];
result( "This is my input string", buffer, elementsof(buffer) );
即使输入字符串比输出缓冲区大,您也可以,因为只有足够的字符串会被复制到缓冲区中

现在,您还可以使用
StringBuilder
从C#调用一个函数,因为您可以分配
StringBuilder
并将其长度传入:

[DllImport(
    "TEST_DLL.dll",
    CallingConvention = CallingConvention.Cdecl,
    CharSet = CharSet.Ansi,
    SetLastError = true
)]
public static extern void result(
    string sString,
    StringBuilder response,
    int cchResponse
);

StringBuilder buffer( 10 );
result( "This is my input string", buffer, buffer.Capacity );
与上面的C/C++示例一样,即使输入字符串大于缓冲区,函数
result()
也只会复制缓冲区中可用的字符数

一句话:如果将
StringBuilder
传递到C/C++函数中以接收该函数的输出,则必须预先分配该函数,并且C/C++函数必须提供一种告诉它最大长度的方法

(我写这篇文章时没有测试代码;这里可能会有错误,但您应该了解大概情况。)