gpt4 book ai didi

c# - C# 中的 C 回调函数问题 - 如何将值传递给指针?

转载 作者:行者123 更新时间:2023-11-30 18:09:44 25 4
gpt4 key购买 nike

我有一个 C 回调定义如下:

Int16 (CALLBACK *ProcessMessage)(Uint16 ServerId,
const char PTR *RequestMsg, Uint32 RequestSize,
char PTR **ResponseMsg, Uint32 PTR *ResponseSize,
Int16 PTR *AppErrCode);

在 C 中使用此回调的示例:

Int16 CALLBACK ProcessMessage(Uint16 ServerId, const char PTR *RequestMsg, Uint32 RequestSize, char PTR **ResponseMsg, Uint32 PTR *ResponseSize, Int16 PTR *AppErrCode){    printf("ProcessMessage() -> ServerId=%u\n", ServerId);    //**** SET THE VALUE FOR RESPONSEMSG (POINTER), THAT'S WHAT I NEED TO DO IN C# ****           sprintf(resp,"(%05lu) REPLY TEST", ServerId);    *ResponseMsg = resp;    printf("ProcessMessage() -> atribuido %p(p) a *ResponseMsg\n", *ResponseMsg);    *ResponseSize = strlen(*ResponseMsg);    *AppErrCode = -1;     return SS_OK;}

Then I've this callback implemented in C#:

 [DllImport("Custom.dll", SetLastError = true)]
static extern Int16 SS_Initialize(
UInt16[] ServerIds,
UInt16 ServerQty,
[MarshalAs(UnmanagedType.LPStr)] string Binding,
[MarshalAs(UnmanagedType.LPStr)] string LogPath,
UInt16 LogDays,
Int16 LogLevel,
UInt16 MaxThreads,
UInt16 MaxConThread,
ProcessMessageCallback callback);

回调定义:

public delegate Int16 ProcessMessageCallback(
UInt16 ServerId,
[MarshalAs(UnmanagedType.LPStr)] string RequestMsg,
UInt32 RequestSize,
[MarshalAs(UnmanagedType.LPStr)] ref string ResponseMsg,
ref UInt32 ResponseSize,
ref Int16 AppErrCode);

设置回调的方法:

public void Call_SS_Initialize(
UInt16[] serverIds,
string binding,
string logPath,
UInt16 logDays,
Int16 logLevel,
UInt16 maxThreads,
UInt16 maxConThread
)
{
Int16 ret;
try
{
pmc = new ProcessMessageCallback(ProcessMessage);

ret = SS_Initialize(
serverIds,
Convert.ToUInt16(serverIds.ToList().Count),
binding,
logPath,
logDays,
logLevel,
maxThreads,
maxConThread,
pmc);
}
}

最后是回调方法,问题在于:

public Int16 ProcessMessage(
UInt16 ServerId,
string RequestMsg,
UInt32 RequestSize,
ref string ResponseMsg,
ref UInt32 ResponseSize,
ref Int16 AppErrCode)
{
//Implement return to ResponseMsg POINTER
}

问题是,ResponseMsg实际上是C中的POINTER。所以在C#方法ProcesMessage中,我必须设置为ResponseMsg DLL 从中获取字符串的内存空间(指针)。

我不能简单地设置 ResponseMsg = "REPLY",因为当该方法完成时,字符串所在的内存已经被销毁。

我怎样才能做到这一点?欢迎任何建议!!

谢谢!

最佳答案

这就是我为重新创建它所做的事情。也许我的实验会有所帮助。

C# 代码:

public delegate void ProcessMessageCallback(
[MarshalAs(UnmanagedType.LPStr)] ref string ResponseMsg);

static class test
{
[DllImport("test.dll")]
static extern void TestCallback(ProcessMessageCallback callback);

static public void Main(string[] args)
{
TestCallback(MyCallback);
}

static void MyCallback(ref string ResponseMsg)
{
ResponseMsg = "hi there";
}
}

C 代码(在 DLL 中):

#include <windows.h>
#include "objbase.h"

__declspec(dllexport) void TestCallback(
void (* CALLBACK managedCallback(char **)))
{
char *test = NULL;
managedCallback(&test);
printf(test);
CoTaskMemFree(test); // NB!
}

这成功打印出“hi There”。

注意:CoTaskMemFree 应该用于释放 P/Invoke 层分配的内存。如果您希望返回的字符串保留的时间比调用 C# 回调的方法的时间长,请考虑在释放返回的内存之前将其复制到另一个位置。

关于c# - C# 中的 C 回调函数问题 - 如何将值传递给指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1241080/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com