Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.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++;非托管DLL到C# 我在C++中有非托管DLL,它工作正常,我尝试用C语言重新实现它,但是我得到以下错误:_C#_C++_Unmanagedexports - Fatal编程技术网

如何转换C++;非托管DLL到C# 我在C++中有非托管DLL,它工作正常,我尝试用C语言重新实现它,但是我得到以下错误:

如何转换C++;非托管DLL到C# 我在C++中有非托管DLL,它工作正常,我尝试用C语言重新实现它,但是我得到以下错误:,c#,c++,unmanagedexports,C#,C++,Unmanagedexports,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

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 convertonative(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);
[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}");
        }
    }
}
一些变化:

C++,
std::string
unsigned char*
,因为在C#中封送它很困难

C#,
对象上下文
IntPtr上下文
,因为
send#u操作
是一个结构,这将传递装箱的对象而不是结构数据

public delegate void Send(int sessionId, sbyte channelId,
    sbyte[] buffer, int len, IntPtr context);
如何通过:

IntPtr ptr = IntPtr.Zero;
try
{
    ptr = Marshal.AllocHGlobal(Marshal.SizeOf(op));
    Marshal.StructureToPtr(op, ptr, false);
    config.send_data(session_id, op.channel_id, bytes, op.data.Length, ptr);
}
finally
{
    Marshal.FreeHGlobal(ptr);
}

我以前做过这种工作,其中一件事就是“打包”/“单词对齐”

确认发送操作的确切大小

在C#中,使用
StructLayout
属性指定结构的等效打包,以便

[StructLayout(LayoutKind.Sequential), Pack = 1] // for byte alignment
[StructLayout(LayoutKind.Sequential), Pack = 2] // for word (2 byte) alignment
[StructLayout(LayoutKind.Sequential), Pack = 4] // for native 32 bit (4 byte) alignment
或者如果有必要的话

[StructLayout(LayoutKind.Explicit)]
这要求每个成员都具有
FieldOffset
属性

[FieldOffset(0)]  // for 1st member
[FieldOffset(4)]  // 4 bytes from beginning of struct

在C++和.Net之间进行集成时,最好明确说明结构类型的这一方面。

为什么所有的
sbyte
?C++版本没有使用它们,通常它们是超级RARESO,对于const unChar char和unchar char,什么是最好的映射对象?haroldIn C#字节通常用
byte
(以及字节数组、字节跨度等)事件和byte&byte[]表示。我得到了相同的错误,所以我想应该是方法参数有问题。那么,你是否知道C++中C++代码的编写方法?这是问题的最后一个参数,盒装结构不能转换成类似于本机类型的任何东西。在C接口中通常使用“上下文”类型的参数传递指针到C++对象,因此很容易将其转换为成员函数调用。当然,你没有C++对象。有点可疑的是,它被使用了,没有任何回调的迹象,但我们看得不够。因此,在委托声明中从object更改为IntPtr,并传递IntPtr.Zero。谢谢你的代码,我想应该在方法调用中将字节改为sbytes,对吗?我做了,但当会话调用时,应用程序崩溃了。正如我已经解释的,它是第三方应用程序,我不知道如何处理sEndDATA,只需工作在C++代码中工作良好的黑盒,但是如果不能更改C++库代码,则需要在C语言中实现<代码> STD::String 。不幸的是,标准库的实现是多种多样的。。。字节和字节都是二进制的,所以你可以选择。我不需要改变C++库,它工作正常。我只想把它翻译成C#正如我在前面的评论中所说的,然后您还需要将
std::string
翻译成C#,但是1。这取决于您链接的标准库,2。这是一个复杂的类。谢谢@shingo,但我的问题是如何翻译std::string?
[FieldOffset(0)]  // for 1st member
[FieldOffset(4)]  // 4 bytes from beginning of struct