作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 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/
我是一名优秀的程序员,十分优秀!