C#< - > C ++:封送包含Char []的[In,Out]结构

时间:2016-11-07 18:27:19

标签: c# c++ struct pinvoke marshalling

我有一个C ++ .dll(无法对代码进行更改)我试图调用一个带有Struct类型的引用参数(也在.dll中定义)的函数。

该函数要求Struct具有' paramName'和' groupName'填充的字段,并根据这些字段,它将返回结构,并填充其余字段。

我没有收到任何编组错误,但是,库调用返回错误代码,调试日志显示它正在接收两个字符串字段的空字符串(请参阅下面的字段设置方式)。我的假设是这个结构的大小没有在托管和非托管表示之间对齐,因此结构不是blittable。

这是C ++方法签名:

int GetConfigs(int contextHandle, Configs* configs);

C ++ Configs结构:

struct Configs {    
    int myInt;
    float myFloat;
    bool flag;
    char name[64];
    char group[64];
}  

C#函数包装器:

[DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int GetConfigs(int contextHandle, [MarshalAs(UnmanagedType.Struct), In, Out] ref Configs configs);

C#结构定义:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Configs
{
    public int myInt;
    public float myFloat;
    [MarshalAs(UnmanagedType.U1)]
    public bool flag;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
    public string name;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
    public string group;
}

根据Microsoft documentation,我已经声明C ++ char []用C#表示字符串,并编组为ByValTStr并设置大小。 同样来自Microsoft documentation

  • bool不是blittable,所以我用明确的MarshalAs标记它。
  • float也不是blittable,但将这些字段声明为float或double在原始问题中没有任何区别。

最后,C#调用代码:

var configs = new Library.Configs
{
    name = "testName",
    group = "testGroup"
};

var returnCode = Library.GetConfigs(GetContextId(), ref configs);

返回代码作为失败代码返回,库调试输出文件显示struct参数:

name = []

(当我通过C#代码调试时,名称显然设置为我在调用时的预期)

而不是将字符串字段声明为

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string name;

我试过了:

[MarshalAs(UnmanagedType.ByValArray,  SizeConst = 64)]
public byte[] name;

但这也没有区别。

1 个答案:

答案 0 :(得分:0)

float / double是抛出结构字节大小的东西 - 库期望一个4字节的浮点数,但默认情况下数据封送器将这些数字保持为8个字节。修复与上面评论中提到的布尔值一起解决了问题:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
    </head>
    <body>

        <script src="https://d3js.org/d3.v4.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

        <script type="text/javascript" charset="utf-8">


          var people = [];

           $(document).ready(function() {
             $.get('data.csv', function(data){

               var lines = data.split('\n');
               var properties = ["position", "name", "salary", "points", "team"]

               for (var i = 0; i < lines.length; i++){
                 var person = lines[i].split(',');
                 var tmpPlayer = {}
                 for (var n = 0; n < person.length; n++){
                   tmpPlayer[properties[n]] = person[n]
                 }
                 people.push(tmpPlayer);
               }
               alert(people[1]["name"]);
               render();
             });



           });


           function render(){
             alert(people[1].name);
           }
        </script>
    </body>
</html>