1

我在调用外部库函数时编组结构时遇到了一些麻烦。我没有从调用本身得到任何错误,但是该函数返回一个错误代码,表明它没有正确理解传入的值。

这是C函数的签名

DLLExport int connect(Client handle, connectOptions* options);

这是我的内部功能

[DllImport("some.dll", CharSet = CharSet.Auto, ExactSpelling = false,
        CallingConvention = CallingConvention.Cdecl)]
    private static extern int connect(IntPtr client, connectOptions options);

connectOptions这是我正在使用的结构的规范

char    struct_id [4]
int     struct_version
int     keepAliveInterval
int     cleansession
int     reliable
willOptions *   will
char *  username
char *  password
int     connectTimeout
int     retryInterval

最后是我的应用程序中的课程

[StructLayout(LayoutKind.Sequential)]
public class connectOptions
{
    public byte[] struct_id;
    public Int32 struct_version;
    public Int32 keepAliveInterval;
    public Int32 cleansession;
    public Int32 reliable;
    public willOptions will;
    [MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
    public string username;
    [MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
    public string password;
    public Int32 connectTimeout;
    public Int32 retryInterval;

    public connectOptions()
    {
        struct_id = Encoding.ASCII.GetBytes("WXYZ");
        struct_version = 0;
        keepAliveInterval = 20;
        cleansession = 1;
        reliable = 0;
        username = string.Empty;
        password = string.Empty;
        connectTimeout = 10;
        retryInterval = 1;
        will = null;
    }
}

[StructLayout(LayoutKind.Sequential)]
public class willOptions
{
    public byte[] struct_id;
    Int32 struct_version;
    [MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
    public string topicName;
    [MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
    public string message;
    public Int32 retained;
    public Int32 qos;

    public willOptions()
    {
        struct_id = Encoding.ASCII.GetBytes("VWXY");
        struct_version = 0;
    }
}
4

2 回答 2

2

我认为你必须struct_id像这样装饰:

[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=4, ArraySubType=UnmanagedType.U1)] 
public byte[] struct_id;

否则 C# 结构将包含对数组的引用,而 C++ 结构包含实际的 4 字节数组。

于 2012-04-12T16:47:51.070 回答
1

您需要将 a 添加SizeConststruct_idand 并将其从usernameand中删除password。该SizeConst参数指示数组或字符串的内存在结构内存储为常量大小的数组,而不是指针。

例如以下是有效的:

C:

struct c_struct {
   char value[100];
}

C#:

public struct c_struct {
     [MarshalAs(UnmanagedType.LPStr, SizeConst = 128)]
     public string value;
}

你的结构定义应该是:

[StructLayout(LayoutKind.Sequential)]
public class connectOptions
{
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst=4, ArraySubType=UnmanagedType.U1)]
    public byte[] struct_id;
    public Int32 struct_version;
    public Int32 keepAliveInterval;
    public Int32 cleansession;
    public Int32 reliable;
    public willOptions will;
    public string username;
    public string password;
    public Int32 connectTimeout;
    public Int32 retryInterval;

    public connectOptions()
    {
        struct_id = Encoding.ASCII.GetBytes("WXYZ");
        struct_version = 0;
        keepAliveInterval = 20;
        cleansession = 1;
        reliable = 0;
        username = string.Empty;
        password = string.Empty;
        connectTimeout = 10;
        retryInterval = 1;
        will = null;
    }
}
于 2012-04-12T16:52:54.477 回答