求助C#大牛!调用C++编译的dll数据类型转换的问题。

jeffreyhu1990 2012-04-06 10:18:45
我将下面一段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#中就是这样写的啊。求助各位大神!
...全文
251 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
家鸣 2012-04-06
  • 打赏
  • 举报
回复
试试:

[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);


菊花古剑和酒 2012-04-06
  • 打赏
  • 举报
回复
和我发的这个贴 http://topic.csdn.net/u/20120406/08/8466dcdf-e855-46f0-a2ec-78ed77149d2c.html?86138 类似,但是没人回答,郁闷
vinjent 2012-04-06
  • 打赏
  • 举报
回复
public static extern int TestStruct(int field_count, ref FIELD_st[] fields);
.
.
.

int result = TestStruct(4,ref fb);
家鸣 2012-04-06
  • 打赏
  • 举报
回复
 
//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;
}


jeffreyhu1990 2012-04-06
  • 打赏
  • 举报
回复
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;
}
vinjent 2012-04-06
  • 打赏
  • 举报
回复
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;
}
jeffreyhu1990 2012-04-06
  • 打赏
  • 举报
回复
我刚才又试了一下,调用那个TestStruct函数以后,fb结构体数组里面的所有内容全部都没了,变成了0和空字符串,不知道这是怎么回事。
EnForGrass 2012-04-06
  • 打赏
  • 举报
回复
[Quote=引用楼主 的回复:]
我将下面一段C++编译成dll,其中函数的参数是一个结构体数组,但是在C#中调用这个函数就出现了问题:
#include "stdafx.h"
typedef struct tagFIELD_st{
char name[64];
unsigned short type;
unsigned int len;
double simdis;
char tblname[64];
……
[/Quote]
注意结构体的参数类型以及字符集编码(看看C++中的编码,C#对应起来)
真相重于对错 2012-04-06
  • 打赏
  • 举报
回复
注意字符串编码?
真相重于对错 2012-04-06
  • 打赏
  • 举报
回复
try
fieldoffset
vinjent 2012-04-06
  • 打赏
  • 举报
回复
你的回傳值是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;
}
}
}
jeffreyhu1990 2012-04-06
  • 打赏
  • 举报
回复
我知道问题出在哪里了,原来我C的那个项目中的结构成员对齐设定的是1字节。。。那么请问C#中有没有相应的设置呢?
小志 2012-04-06
  • 打赏
  • 举报
回复
不好意思,长度是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;
}
小志 2012-04-06
  • 打赏
  • 举报
回复
[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;
}
jeffreyhu1990 2012-04-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

试试:
C# code

[DllImport("D:\\mongoebase\\StructDll\\Debug\\StructDll.dll", CharSet = CharSet.ANSI)]
public static extern int TestStruct(int field_count, [In, Out, MarshalAs(UnmanagedType.LPArray)] ……
[/Quote]
我觉得应该是这个参数[In, Out, MarshalAs(UnmanagedType.LPArray)]设置的问题,能详细的解释一下这个参数的作用吗?
jeffreyhu1990 2012-04-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

试试:
C# code

[DllImport("D:\\mongoebase\\StructDll\\Debug\\StructDll.dll", CharSet = CharSet.ANSI)]
public static extern int TestStruct(int field_count, [In, Out, MarshalAs(UnmanagedType.LPArray)] ……
[/Quote]
你说的这个方法我试了,结构体数组传递到函数里面以后只有第一个元素有值是正确的,后面的三个元素还是不对。

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧