C#调用DLL的问题(如何以传址方式传递一个结构数组?)
各位大哥,我用VC做了一个DLL,其中有一个函数是这样的:int _stdcall gsmParseMessageList(SM_PARAM* pMsg)
{
……………………
}
上面定义的SM_PARAM结构在C#中的定义如下:
public struct SM_PARAM
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string SCA;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TPA;
public char TP_PID;
public char TP_DCS;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TP_SCTS;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)]
public string TP_UD;
short index;
};
我定义了 SM_PARAM [] msg=new SM_PARAM [10] 这样一个数组,但是因为
C#默认不支持指针的,我要以传址的方式传递一个结构数组,在DLL如何声名?之前我试过
这样:
[DllImport("D:\\DLL\\temp\\Debug\\mmt.dll")]
public static extern int gsmParseMessageList (ref SM_PARAM [] msg);
但是这就相当于传递了一个二级指针了,只有将DLL中的int _stdcall gsmParseMessageList(SM_PARAM* pMsg)改为int _stdcall gsmParseMessageList(SM_PARAM** pMsg)才能正常运行,但我只要以传址的方式传递一个结构数组到gsmParseMessageList(SM_PARAM* pMsg)中,请问我要怎么做?希望大家帮帮忙,小弟感激不尽,谢谢!
--------------------编程问答-------------------- 顶!!! --------------------编程问答-------------------- 哪位高手可以帮帮忙阿?实在很急阿,谢谢啦 --------------------编程问答-------------------- 友情一顶 --------------------编程问答-------------------- ref --------------------编程问答-------------------- ref params msg --------------------编程问答-------------------- 上面这样做是不行的,因为在定义的DLL中只会认为你是传递一个结构,我要的是传递一个结构数组 --------------------编程问答-------------------- dll 声明
[dllimport.... ]
int gsmParseMessageList(IntPtr pMsg)
调用
SM_PARAM[] arr = ....
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement ( arr,0);
gsmParseMessageList( ptr ); --------------------编程问答-------------------- 我刚试了,可以调用,谢谢各位,但是,我一运行就提示:"未处理AccessViolationException,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。",请问如何解决?谢谢! --------------------编程问答-------------------- up --------------------编程问答-------------------- struct的 c++ 声明
--------------------编程问答-------------------- hdt大哥,请问要改哪里阿?麻烦您了,可说明一下吗,非常感谢!这是我在C#中的STRUCT
public struct SM_PARAM
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string SCA;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TPA;
public char TP_PID;
public char TP_DCS;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TP_SCTS;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)]
public string TP_UD;
short index;
};
--------------------编程问答-------------------- 实在不行就unsafe吧~~ --------------------编程问答-------------------- 到了最后关头,再用吧,谢谢各位! --------------------编程问答-------------------- 把c++的struct声明贴出来
--------------------编程问答-------------------- C++的STRUCT声明是这样的:
typedef struct {
char SCA[16];
char TPA[16];
char TP_PID;
char TP_DCS;
char TP_SCTS[16];
char TP_UD[160];
short index;
} SM_PARAM; --------------------编程问答-------------------- 定义方式:
[DllImport("D:\\DLL\\temp\\Debug\\mmt.dll")]
public static extern int gsmParseMessageList (ref SM_PARAM msg);
调用方式:
SM_PARAM [] msg=new SM_PARAM [10] ;
gsmParseMessageList( ref msg[0]);
试试,有奇效 --------------------编程问答-------------------- 以前遇到过,最后用unsafe解决。 --------------------编程问答-------------------- try
[StructLayout(LayoutKind.Sequential )]
public class SM_PARAM
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string SCA;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TPA;
public char TP_PID;
public char TP_DCS;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string TP_SCTS;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 160)]
public string TP_UD;
short index;
};
函数定义
[DllImport("your.DLL", CharSet=CharSet.ANSI )]
int gsmParseMessageList(IntPtr pMsg);
--------------------编程问答-------------------- 或者用unsafe自己修飾一下 --------------------编程问答-------------------- 小弟在此谢过各位大哥了,尤其是hdt大哥,我刚试了,还是会出现"未处理AccessViolationException,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。",看来只能用UNSAFE了,非常感谢各位 --------------------编程问答-------------------- 试过我的方法没,我以前的问题就是这个方法解决的
使用一直正常 --------------------编程问答-------------------- KingDomgps大哥,你的方法我也试过了,的确好用,不过还是会出现这个问题,因为我要返回多个值,将结果返回到SM_PARAM结构,所以不是因为我在gsmParseMessageList中修改了SM_PARAM结构引起这个错误? --------------------编程问答-------------------- KingDomgps大哥,是不是我这里
SM_PARAM [] msg=new SM_PARAM [10] ;
gsmParseMessageList( ref msg[0]);
有什么问题? --------------------编程问答-------------------- 牵强付会,用C++就用C++,用CSharp就用Csharp,互操作是微软向下兼容的策略,为什么不把时间放在上面 --------------------编程问答-------------------- mark! --------------------编程问答-------------------- 在你的结构体定义前面加上[StructLayout(LayoutKind.Sequential )]
然后再试试把你的数组改大一点传进去试试,有可能是数组越界哦 --------------------编程问答-------------------- 除 --------------------编程问答-------------------- “未处理AccessViolationException,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”这样的错误应该是数据保护。
最近也遇到过类似问题,不过是c++调用delphi的时候出现的。你尝试一下在C#内使用Array.Clear(test,0,65536);
先清零数据。
在C++中使用 void * 作为形参,然后c++内所有操作使用 强制类型转换后的指针自增、自减操作来完成。不知道这样的方式是否可以解决你的问题。
--------------------编程问答-------------------- 该回复被版主删除 --------------------编程问答-------------------- 多谢名位的帮助,还是上面那位兄弟说得对,以前为了兼容别人做的DLL没办法,不过发现在C#这样调用太没效率,还是用C#自己重做吧. --------------------编程问答-------------------- 感谢26楼的朋友,解决了我的问题。
[DllImport("***.dll")]
public static extern short ReadRecord(IntPtr hCom, byte Adr, byte Cmd, ref RecordS Record, string FileName, byte Bz);
这个方法是批量读取,Record返回的是一个结构数组 传数组的第一个元素是正解ref Record[0] --------------------编程问答-------------------- C#结构数组!还来个指针!...这段用C吧
C#不合适..
补充:.NET技术 , C#