【发布时间】:2019-09-17 09:24:09
【问题描述】:
我在 C++ 中有非托管 dll,它工作正常,我尝试用 C# 重新实现它,但出现以下错误:
System.ArgumentException:值不在预期范围内
at System.StubHelpers.ObjectMarshaler.ConvertToNative(Object objSrc, IntPtr pDstVariant) at Demo.on_session_available(Int32 session_id) in C:\\Users\\Peyma\\Source\\Repos\\FastViewerDataClient\\FastViewerDataClient\\Demo.cs:line 69异常方法:8
转换为原生
mscorlib,版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089
System.StubHelpers.ObjectMarshaler
void ConvertToNative(System.Object, IntPtr)HResult:-2147024809
来源:mscorlib
C++代码如下:
typedef void(*func_ptr)(
int sId,
unsigned char cId,
const unsigned char* buf,
int len,
void* context);
struct configuration
{
func_ptr send;
};
struct send_operation
{
int session_id;
unsigned char channel_id;
std::string data;
};
auto op = new send_operation();
op->sId = sessionId;
op->cId = channelId;
op->data = "Some Text";
configuration.send(
sessionId,
channelId,
reinterpret_cast<const unsigned char*>(op->data.c_str()),
op->data.length(),
op);
然后用 C# 翻译如下:
[StructLayout(LayoutKind.Sequential)]
public struct Configuration
{
public Send send { get; set; }
}
[StructLayout(LayoutKind.Sequential)]
public struct send_operation
{
public int session_id { get; set; }
public sbyte channel_id { get; set; }
public string data { get; set; }
};
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void Send(int sessionId, sbyte channelId, sbyte[] buffer, int len, object context);
var op = new send_operation
{
session_id = session_id,
channel_id = 0,
data = "This is a test message!!"
};
var bytes = Encoding.UTF8.GetBytes(op.data);
config.send(sessionId, 0, Array.ConvertAll(bytes, Convert.ToSByte), op.data.Length, op);
更新:
public static void on_session_available(int session_id)
{
WriteOnFile($"Open session id:{session_id}");
try
{
var op = new send_operation
{
session_id = session_id,
channel_id = 0,
data = "This is a test message!!"
};
var bytes = Encoding.UTF8.GetBytes(op.data);
config.send_data(session_id, op.channel_id, bytes, op.data.Length, op);
}
catch (Exception e)
{
WriteOnFile($"Error in sending data:{JsonConvert.SerializeObject(e)}");
if (e.InnerException != null)
{
WriteOnFile($"Error in inner sending data:{e.InnerException.Message}");
}
}
}
【问题讨论】:
-
为什么都是
sbyte? C++ 版本没有使用它们,通常它们非常罕见 -
那么 const unsigned char* 和 unsigned char 的最佳映射对象是什么? @哈罗德
-
在 C# 中,字节通常用
byte表示(以及字节数组、字节范围等) -
Event with byte & byte[] 我得到了同样的错误,所以我想应该是方法参数有问题。那么你知道如何用 C# 编写这些 C++ 代码吗?
-
这是问题的最后一个参数,装箱的结构无法转换为任何类似于本机类型的东西。 “上下文”类型的参数通常在 C 接口中用于传递指向 C++ 对象的指针,因此很容易将其转换为成员函数调用。你当然没有 C++ 对象。它完全被使用有点可疑,没有任何回调的迹象,但我们看不到足够的东西。因此,在委托声明中从 object 更改为 IntPtr 并传递 IntPtr.Zero。 Kabloom 如果它确实被使用了。
标签: c# c++ unmanagedexports