一:
struct MAPI_DATA_SET_TX_FREQUENCY_CMD
{
/** Present optional arguments. */
unsigned int Options[10];
/** AutoSet value. */
unsigned char AutoSet;
/** CenterFrequency value. */
unsigned short CenterFrequency;
/** InventoryFilterAPattern value. */
unsigned char * InventoryFilterAPattern;
/** HaltFilterAMask value. */
unsigned short * HaltFilterAMask; /** Data */
void * Data;
/** Handle to handle */
Handle hFile; /** pointer to a Window*/
HWND hDlgMain;
};
struct MAPI_DATA_SET_TX_FREQUENCY_CMD
{
/** Present optional arguments. */
unsigned int Options[10];
/** AutoSet value. */
unsigned char AutoSet;
/** CenterFrequency value. */
unsigned short CenterFrequency;
/** InventoryFilterAPattern value. */
unsigned char * InventoryFilterAPattern;
/** HaltFilterAMask value. */
unsigned short * HaltFilterAMask; /** Data */
void * Data;
/** Handle to handle */
Handle hFile; /** pointer to a Window*/
HWND hDlgMain;
};
public struct test
{
string oid;
string value;
}
只不过HWND和handle就比较麻烦了
Handle 和HWND在.net里都有对应的类的
MAPI_DATA_SET_TX_FREQUENCY_CMD GetData();
当调用该函数成功(在C#中使用[Dllimport]进行引入了)后,其成员(C#中是不是叫字段?) Data是void *(当然在C#结构体中我们可能用IntPtr来代替该指针),那么在C#中如何将该指针转换为结构呢?是不是必须使用如下unsafe方法才能提取其中的细节数据?有没有不用unsafe的方法?
MAPI_DATA_SET_TX_FREQUENCY_CMD mapiData = GetData();
unsafe
{
MyStruct *pMyStruct = (MyStruct *)mapiData.Data;
pMyStruct->......
}
public struct MAPI_DATA_SET_TX_FREQUENCY_CMD
{
/** Present optional arguments. */
unsigned int Options[10];// 这里不知如何处理?
/** AutoSet value. */
// unsigned char AutoSet;
byte AutoSet;
/** CenterFrequency value. */
// unsigned short CenterFrequency;
ushort CenterFrequency;
/** InventoryFilterAPattern value. */
unsigned char * InventoryFilterAPattern;// 这里不知如何处理?
/** HaltFilterAMask value. */
unsigned short * HaltFilterAMask;// 这里不知如何处理? /** Data */
// void * Data;
IntPtr Data;// 是否可以这样?
/** Handle to handle */
Handle hFile;// 这里不知如何处理? /** pointer to a Window*/
HWND hDlgMain;// 这里不知如何处理?
};
[StructLayout(LayoutKind.Sequential)]
struct MAPI_DATA_SET_TX_FREQUENCY_CMD
{
/** Present optional arguments. */
uint Options[10];
/** AutoSet value. */
byte AutoSet;
/** CenterFrequency value. */
ushort CenterFrequency;
/** InventoryFilterAPattern value. */
string InventoryFilterAPattern;
/** HaltFilterAMask value. */
ref ushort HaltFilterAMask; /** Data */
System.IntPtr Data;
/** Handle to handle */
System.IntPtr hFile; /** pointer to a Window*/
System.IntPtr hDlgMain;
}
char *可以理解为一个数组型的,用string就行了
[StructLayout(LayoutKind.Sequential)]
public struct MAPI_DATA_SET_TX_FREQUENCY_CMD {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public uint[] Options;
/** AutoSet value. */
public byte AutoSet;
/** CenterFrequency value. */
public ushort CenterFrequency; /** InventoryFilterAPattern value. */
public IntPtr InventoryFilterAPattern; /** HaltFilterAMask value. */
public IntPtr HaltFilterAMask; /** Data */
public IntPtr Data; /** Handle to handle */
public IntPtr hFile; /** pointer to a Window*/
public IntPtr hDlgMain;
}
问题1:uint Options[10];//这种声明是不行的,C#中声明数组,然后我把它改成:uint[10] Options;此时出现下述错误:
错误 1 不能在变量声明中指定数组大小(请尝试使用“new”表达式初始化)
问题2:ref ushort HaltFilterAMask;// 这种定义导致如下错误
错误 2 类、结构或接口成员声明中的标记“ref”无效
C++中的HANDLE在C#中有IntPtr表示。
另外,在调用C++的函数时,可以在参数前用[MarshalAs(UnmanagedType.类型)]指定托管/非托管对应关系。
按照你的帮助,我做了如下示例:编译可以通过,但是执行的时候出现异常:nullReferenceException,提示如下:未将对象引用设置到对象的实例。我的例程代码如下:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MAPI_DATA_SET_TX_FREQUENCY_CMD myStruct = new MAPI_DATA_SET_TX_FREQUENCY_CMD();
myStruct.Options[0] = 10;// 执行到这里出现异常
myStruct.Options[1] = 10;
}
[StructLayout(LayoutKind.Sequential)]
public struct MAPI_DATA_SET_TX_FREQUENCY_CMD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public uint[] Options;
/** AutoSet value. */
public byte AutoSet;
/** CenterFrequency value. */
public ushort CenterFrequency; /** InventoryFilterAPattern value. */
public IntPtr InventoryFilterAPattern; /** HaltFilterAMask value. */
public IntPtr HaltFilterAMask; /** Data */
public IntPtr Data; /** Handle to handle */
public IntPtr hFile; /** pointer to a Window*/
public IntPtr hDlgMain;
}
}
}
static void Main(string[] args)
{
MAPI_DATA_SET_TX_FREQUENCY_CMD myStruct = new MAPI_DATA_SET_TX_FREQUENCY_CMD();
myStruct.Options = new uint[10];// 分配空间
myStruct.Options[1] = 10;
}
“C++里的结构体在C#中一般用类表示,可以在调用函数外定义一个类,然后在调用函数处声明这个类的实例即可。”--------C++中都是声明为struct的,在C#中如果改为类,这样传到非托管的C++动态库(dll)的函数中行不行?希望给一个确定的答案!谢谢!!!
1、数值型直接用对应的就可。(DWORD -> int , WORD -> Int16) 2、API中字符串指针类型 -> .net中string 3、API中句柄 (dWord) -> .net中IntPtr 4、API中结构 -> .net中结构或者类。注意这种情况下,要先用StructLayout特性限定声明结构或类
字符串指针类型-> .net中string
其它类型的指针呢?如unsigned short * ->.Net中...???
似乎是
int param* ->
[in, out] int[] param我没试过,你看看行不
To nany99():
“C++里的结构体在C#中一般用类表示,可以在调用函数外定义一个类,然后在调用函数处声明 这个类的实例即可。”-- ------C++中都是声明为struct的,在C#中如果改为类,这样传到非托管的C++动态库(dll)的函数中行不行?希望给一个确定的答案!谢谢!!!
==============================
我原来试过调用时用struct和class都可以,但是我通常都用struct,因为C#中struct的行为和C++中的class和struct比较类似。到时候用起来比较好控制。to eeixy2000(老顽童) :
To:ys119(mars)
按照你的帮助,我做了如下示例:编译可以通过,但是执行的时候出现异常:nullReferenceException,提示如下:未将对象引用设置到对象的实例。
===================================
我以为你的这个结构是调用非托管代码后得到的,所以没有写对这个struct内部成员进行初始化的东西。如需要你自己可以设置初始值。如:[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public uint[] Options = new uint[10];
To SmallMummy(笑看人生) :
字符串指针类型-> .net中string
其它类型的指针呢?如unsigned short * ->.Net中...???
========================================
这些指针都可以用IntPtr类型来代替,到时如果要使用数据时通过Marshal类的一些方法可以进行操作。之所以用string来替代字符串指针类型,是因为应用上比较方便,其实用Intptr一样可以,但是需要再转换,就麻烦了。
3、API中句柄 (dWord) -> .net中IntPtr
=========================
API中句柄 DWORD -〉 UIntPtr
对你的提法很感兴趣,能否详细一点?
事实上我也不想用指针,因为要从函数中把数据返回来,这时候就要用到将指针转换为结构或其它的指针,这就需要设置unsafe代码段来进行,这是不好的,所以请讲详细一点,谢谢!
例如当从C++托管函数中返回MAPI_DATA_SET_TX_FREQUENCY_CMD结构类数据时,其数据成员Data(void * Data;)对应另一个结构OtherStruct,我就需要将该(void *Data)(C#中可能定义为IntPtr Data)-->OtherStruct*(又是指针),这就需要声明unsafe代码段!请问你如何解决这个问题,谢谢!
=============================================
To efijki(YD) :
例如当从C++托管函数中返回MAPI_DATA_SET_TX_FREQUENCY_CMD结构类数据时,其数据成员Data(void * Data;)对应另一个结构OtherStruct,我就需要将该(void *Data)(C#中可能定义为IntPtr Data)-->OtherStruct*(又是指针),这就需要声明unsafe代码段!请问你如何解决这个问题,谢谢!
================================================
这个问题,你先定义一个C#中的struct OtherStruct,然后Data(void * Data);-->Data(ref OtherStruct Data);
我实验过的
能否把C#中的定义和调用具体写下来,没有太看明白你的意思!谢啦!!!
[DllImport(dllName, EntryPoint = "f")]
public static extern void f(ref A para);
如果该para有一个IntPtr的成员data,其实际对应某结构(设为MyCsharpStructB)的指针,那么在C#中如何将该data成员转换为MyStructA?看看我这样作是否妥当?
...
MyCsharpStructA para = new MyCsharpStructA();
f(ref para);
unsafe
{
MyCsharpStructB * = (MyCsharpStructB *)para.data;
// Other operation
}
这样就必须用指针了,有没有不用指针的方法?
IntPrt pt = para.data; //这个在结构里面就定义为IntPtr
假如你要使用那个结构的对象:
MyCsharpStructB structB = (MyCsharpStructB) Marshal.PtrToStructure(pt);
C#定义该结构可以如下:
[StructLayout(LayoutKind.Sequential)]
struct MAPI_DATA_SET_TX_FREQUENCY_CMD
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
/** Present optional arguments. */
uint[] Options;
/** AutoSet value. */
byte AutoSet;
/** CenterFrequency value. */
ushort CenterFrequency;
/** InventoryFilterAPattern value. */
string InventoryFilterAPattern;
/** HaltFilterAMask value. */
IntPtr HaltFilterAMask; /** Data */
IntPtr Data;
/** Handle to handle */
IntPtr hFile; /** pointer to a Window*/
IntPtr hDlgMain;
};调用时,可以通过应用传递ref;
返回时可以通过Marshal.PtrToStructure将其中的指针转换为结构,或者如果该指针对应的不是结构体,可以通过Marshal.Copy将数据拷贝到托管变量中!
谢谢各位的帮忙!