DLL的代码如下:
typedef struct cdm_cashunit
{
USHORT usNumber;
USHORT usType;
char cUnitID[5];
char cCurrencyID[3];
ULONG ulValues;
ULONG ulInitialCount;
ULONG ulCount;
ULONG ulMinimum;
ULONG ulMaximum;
USHORT usStatus;
} CDMCASHUNIT, * LPCDMCASHUNIT;typedef struct cdm_cu_info
{
USHORT usTellerID;
USHORT usCount;
LPCDMCASHUNIT *lppList;
} CDMCUINFO, * LPCDMCUINFO;DLLEXPORT int __stdcall GetCashUnitInfo(LPCDMCUINFO CassUnitInfo)C#调用如下: unsafe public class ClassCDM
{
public ClassCDM()
{
} [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct cdm_cashunit
{
public UInt16 usNumber;
public UInt16 usType;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=5 )]
public char[] cUnitID;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=3 )]
public char[] cCurrencyID;
public UInt32 ulValues;
public UInt32 ulInitialCount;
public UInt32 ulCount;
public UInt32 ulMinimum; public UInt32 ulMaximum;
public UInt16 usStatus;
} [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct cdm_cuinfo
{
public UInt16 usTellerID;
public UInt16 usCount;
public IntPtr[] lppList; //这个地方,我拿不准应该是IntPtr,还是IntPtr[]
} [DllImport("cdm.dll")]
private static extern int GetCashUnitInfo(ref cdm_cuinfo cassinfo);
public cdm_cuinfo gCass = new cdm_cuinfo(); public int GetCassInfo()
{
int i,ret;
gCass.lppList=new IntPtr[8];
IntPtr[] buffer=new IntPtr[8];
cdm_cashunit[] cuinfo=new cdm_cashunit[8];
for(i=0;i<8;i++)
{
cuinfo[i].cCurrencyID=new char[3];
cuinfo[i].cUnitID=new char[5]; buffer[i]= Marshal.AllocCoTaskMem( Marshal.SizeOf(cuinfo[i] ));
Marshal.StructureToPtr( cuinfo[i], buffer[i], false );
gCass.lppList[i] = buffer[i];
}
ret=GetCashUnitInfo(ref gCass);
for(i=0;i<8;i++)
{
Marshal.FreeCoTaskMem( buffer[i] ); } return ret; }
}调用的时候就会出现异常:
未处理的“System.Runtime.InteropServices.COMException”类型的异常出现在 CDMTEST.exe 中。其他信息: 格式太旧或是类型库无效。我查了坛子上的其他帖子,也没见到类似的问题。
MSDN中,关于这个问题的示例中,有一个将结构数组作为参数的例子“平台调用数据类型 OutArrayOfStructs 示例”,但它是假设被调用者已经分配了内存,
而我的DLL是要求由调用者来分配内存,而且约定lppList最多不会超出8个。
折腾了一晚上了,也没找到问题在哪??请各位高手帮忙看看,呵呵。
typedef struct cdm_cashunit
{
USHORT usNumber;
USHORT usType;
char cUnitID[5];
char cCurrencyID[3];
ULONG ulValues;
ULONG ulInitialCount;
ULONG ulCount;
ULONG ulMinimum;
ULONG ulMaximum;
USHORT usStatus;
} CDMCASHUNIT, * LPCDMCASHUNIT;typedef struct cdm_cu_info
{
USHORT usTellerID;
USHORT usCount;
LPCDMCASHUNIT *lppList;
} CDMCUINFO, * LPCDMCUINFO;DLLEXPORT int __stdcall GetCashUnitInfo(LPCDMCUINFO CassUnitInfo)C#调用如下: unsafe public class ClassCDM
{
public ClassCDM()
{
} [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct cdm_cashunit
{
public UInt16 usNumber;
public UInt16 usType;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=5 )]
public char[] cUnitID;
[ MarshalAs( UnmanagedType.ByValArray, SizeConst=3 )]
public char[] cCurrencyID;
public UInt32 ulValues;
public UInt32 ulInitialCount;
public UInt32 ulCount;
public UInt32 ulMinimum; public UInt32 ulMaximum;
public UInt16 usStatus;
} [ StructLayout( LayoutKind.Sequential, CharSet=CharSet.Ansi )]
public struct cdm_cuinfo
{
public UInt16 usTellerID;
public UInt16 usCount;
public IntPtr[] lppList; //这个地方,我拿不准应该是IntPtr,还是IntPtr[]
} [DllImport("cdm.dll")]
private static extern int GetCashUnitInfo(ref cdm_cuinfo cassinfo);
public cdm_cuinfo gCass = new cdm_cuinfo(); public int GetCassInfo()
{
int i,ret;
gCass.lppList=new IntPtr[8];
IntPtr[] buffer=new IntPtr[8];
cdm_cashunit[] cuinfo=new cdm_cashunit[8];
for(i=0;i<8;i++)
{
cuinfo[i].cCurrencyID=new char[3];
cuinfo[i].cUnitID=new char[5]; buffer[i]= Marshal.AllocCoTaskMem( Marshal.SizeOf(cuinfo[i] ));
Marshal.StructureToPtr( cuinfo[i], buffer[i], false );
gCass.lppList[i] = buffer[i];
}
ret=GetCashUnitInfo(ref gCass);
for(i=0;i<8;i++)
{
Marshal.FreeCoTaskMem( buffer[i] ); } return ret; }
}调用的时候就会出现异常:
未处理的“System.Runtime.InteropServices.COMException”类型的异常出现在 CDMTEST.exe 中。其他信息: 格式太旧或是类型库无效。我查了坛子上的其他帖子,也没见到类似的问题。
MSDN中,关于这个问题的示例中,有一个将结构数组作为参数的例子“平台调用数据类型 OutArrayOfStructs 示例”,但它是假设被调用者已经分配了内存,
而我的DLL是要求由调用者来分配内存,而且约定lppList最多不会超出8个。
折腾了一晚上了,也没找到问题在哪??请各位高手帮忙看看,呵呵。
解决方案 »
- Linq 属性映射的问题,头疼两天了
- C# Treeview BOM问题求助大侠
- 什么是所谓的IT行业知识?
- winform中,如何在gridview 中高亮显示符合条件的数据行?
- System.Diagnostics.Process.Start相关问题
- @转义?
- 请问C#如何实现静态析构?
- 有谁知道如何将byte数组中的值,复制到非托管结构或类中?高人请进,我已经在这个问题上花了很多时间了.
- 向各位高手请教:如何将progressBar与数据库查询联系起来?
- 未结束的字符串常量
- Help!一窗体内有N个textbox,都有KeyPress事件,重复代码看了就烦!救命!
- 怎样把回车替换成"<p>"
我最初是想着用指针来的,但是编译的时候总是报错,无法获取托管类型的地址。不知道是不是我用的不对,呵呵。
lppList = Marshal.AllocCoTaskMem(sizeof(IntPtr)*8);
之后再调非托管函数,调完之后可以再从lppList中读返回值,读的时候可以用Copy()一次取出来,不用循环,最后再把lppList释放掉,注意放到finally里手边没环境,只能大概说说,楼主还是自己多试试吧^-^
还有,lpplist++,这样不行吗?那怎么样才能操作IntPtr?