我将下面一段C++编译成dll,其中函数的参数是一个结构体数组,但是在C#中调用这个函数就出现了问题:
#include "stdafx.h"
typedef struct tagFIELD_st{
char name[64];
unsigned short type;
unsigned int len;
double simdis;
char tblname[64];
}FIELD_st;
extern "C" __declspec(dllexport) int TestStruct(int field_count,FIELD_st fields[])
{
for (int i=0; i<field_count; i++)
{
switch (fields[i].type) {
case 0x0002:
break;
case 0x0008:
break;
case 0x0010:
break;
case 0x0028:
break;
case 0x0012:
break;
case 0x0014:
break;
case 0x0022:
break;
case    0x0030:
if (fields[i].simdis<0) return -1;
break; case 0x0004:
if (fields[i].len<=1) return -2;
break;
default:
return -3;
break;
};
if (strlen(fields[i].name)==0) return -4;
return 0;
}
}
然后用下面的一段C#代码调用这个dll中的函数TestStruct,结果总是在switch中进入default,返回-3,以下是C#的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
public struct FIELD_st
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
    public string name;
    public UInt16 type;
    public UInt32 len;
    public Double simdis;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
    public string tblname;
}
        [DllImport("D:\\mongoebase\\StructDll\\Debug\\StructDll.dll")]
        public static extern int TestStruct(int field_count, [Out] FIELD_st[] fields);
        static void Main(string[] args)
        {
            FIELD_st[] fb = new FIELD_st[4];
            fb[0].name = "BNO";
            fb[0].type =0x0008;
            fb[1].name = "BNAME";
            fb[1].type = 0x0004;
            fb[1].len = 40;
            fb[2].name = "ANO";
            fb[2].type = 0x0008;
            fb[3].name = "COVER";
            fb[3].type = 0x0008;
            fb[3].len = 0;
            fb[3].simdis = 0.172;
            int result = TestStruct(4, fb);
            Console.WriteLine(result);
            Console.Read();
        }   
    }
}
在C#中调用TestStruct函数,传递的结构体数组参数fb的每个元素的type会在TestStruct中的switch语句中进行比较,我给这个数组的type赋值都是0x0004或者0x0008,但是执行在switch语句中却没有进入case 0x0004和case 0x0008,而是全部都进入了default,请问这是为什么?是我将C中的struct结构转换到C#中有问题吗?但是我查找过很多资料说C中的struct结构转换到C#中就是这样写的啊。求助各位大神!

解决方案 »

  1.   

    我刚才又试了一下,调用那个TestStruct函数以后,fb结构体数组里面的所有内容全部都没了,变成了0和空字符串,不知道这是怎么回事。
      

  2.   

    public struct FIELD_st

      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
      public String name; 
      public UInt16 type; 
      public UInt32 len; 
      public double simdis; 
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
      public String tblname; 
    }
      

  3.   

    C#对应的类型应该没问题啊,网上很多文章说就是这样对应的。现在我让TestStruct函数光输出结构体数组fb的内容,结果全部都是0和空字符串,这是为什么?extern "C" __declspec(dllexport) int TestStruct(int field_count,const FIELD_st fields[])
    {
    for (int i=0; i<field_count; i++)
    {
    cout<<fields[i].type<<endl;
    }
    return 0;
    }
      

  4.   

    public static extern int TestStruct(int field_count, ref FIELD_st[] fields);

    .
    .int result = TestStruct(4,ref fb);
      

  5.   

    和我发的这个贴 http://topic.csdn.net/u/20120406/08/8466dcdf-e855-46f0-a2ec-78ed77149d2c.html?86138 类似,但是没人回答,郁闷
      

  6.   

    试试:[DllImport("D:\\mongoebase\\StructDll\\Debug\\StructDll.dll", CharSet = CharSet.ANSI)]
    public static extern int TestStruct(int field_count, [In, Out, MarshalAs(UnmanagedType.LPArray)] FIELD_st[] fields);
     
      

  7.   

    我觉得应该是这个参数[In, Out, MarshalAs(UnmanagedType.LPArray)]设置的问题,能详细的解释一下这个参数的作用吗?
      

  8.   

    [StructLayout(LayoutKind.Sequential)]
    public struct FIELD_st
    {
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
      public char[] name;
      public UInt16 type;
      public UInt32 len;
      public Double simdis;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
      public char[] tblname;
    }
      

  9.   

    不好意思,长度是64,写成4了
    [StructLayout(LayoutKind.Sequential)]
    public struct FIELD_st
    {
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
      public char[] name;
      public UInt16 type;
      public UInt32 len;
      public Double simdis;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
      public char[] tblname;
    }
      

  10.   

    你的回傳值是0應該是正常的。因為你在c++中的判斷回傳本來就是0
    .h
    # ifndef testStructDll_H_
    # define testStructDll_H_typedef struct tagFIELD_st{ 
    char name[64]; 
    unsigned short type; 
    unsigned int len; 
    double simdis; 
    char tblname[64]; 
    }FIELD_st;
    extern "C" __declspec(dllexport) int TestStruct(int field_count, FIELD_st fields[], int cbSize);
    #endif.cpp
    #include "testStructDll.h"
    #include "string.h"int TestStruct(int field_count, FIELD_st fields[], int cbSize)
    {
    for (int i=0; i<field_count; i++)

    switch (fields[i].type) 
    {
    case 0x0002: 
    break;
    case 0x0008: 
    break;
    case 0x0010: 
    break;
    case 0x0028: 
    break;
    case 0x0012: 
    break;
    case 0x0014: 
    break;
    case 0x0022:
    break; 
    case 0x0030:
    if (fields[i].simdis<0) return -1;
    case 0x0004: 
    if (fields[i].len<=1) return -2;
    default:
    return -3;
    };
    if (strlen(fields[i].name)==0) return -4;
    return 0;
    }
    }
    c#
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;namespace ConsoleApplication1
    {
        class Program
        {
            [StructLayout(LayoutKind.Sequential)]
            public struct FIELD_st
            {
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
                public String name;
                public uint type;
                public UInt32 len;
                public double simdis;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
                public String tblname;
            }        [DllImport(@"H:\我的資料\程式\Visual C++-COM和COM+\testStructDll\Debug\testStructDll.dll", SetLastError = true)]
            public static extern int TestStruct(int field_count, FIELD_st[] fields);        static void Main(string[] args)
            {
                FIELD_st[] fb = new FIELD_st[4];
                fb[0].name = "BNO";
                fb[0].type = 0x0008;
                fb[1].name = "BNAME";
                fb[1].type = 0x0004;
                fb[1].len = 40;
                fb[2].name = "ANO";
                fb[2].type = 0x0008;
                fb[3].name = "COVER";
                fb[3].type = 0x0030;
                fb[3].len = 0;
                fb[3].simdis = 0.172;
                int result = TestStruct((int)fb.Length, fb);
                Console.Write("\n"+result);
                int resultC = TestStructC((int)fb.Length, fb);c#測試
                Console.Write("\n" + resultC);
                Console.Read();
            }        static int TestStructC(int field_count, FIELD_st[] fields)//在c#下進行測試
            {
            for (int i=0; i<field_count; i++)
            { 
            switch (fields[i].type) 
            {
            case 0x0002:
                            break;
            case 0x0008:
                            break;
            case 0x0010:
                            break;
            case 0x0028:
                            break;
            case 0x0012:
                            break;
            case 0x0014:
                            break;
            case 0x0022:
                            break;
            case 0x0030:
            if (fields[i].simdis<0) 
                                return -1;
                            else
                                return 0;
            case 0x0004: 
            if (fields[i].len<=1) 
                                return -2;
                            else
                                return 0;
            default:
                return -3;
            }
                    if (fields[i].name.Length==0) return -4;
                        return 0;
            }
                return 0;
            }
        }
    }
      

  11.   

       
    //Pack 控制类或结构的数据字段在内存中的对齐方式。
    [StructLayout(LayoutKind.Sequential,Pack=1)]
    public struct FIELD_st
    {
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
      public string name;
      public UInt16 type;
      public UInt32 len;
      public Double simdis;
      [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
      public string tblname;
    }