求C#调用联通短信网关UniAPIDll.dll的代码
已经查阅了好多文章,都没有最终成功的解决代码,哪位大侠可以发送下?dingrui.cn@gmail.com
小弟感激不尽。
ps:不要傲天API。
C语言头文件
************************************************************************************************
// uniapi interface header file
#ifndef UNIAPI_H
#define UNIAPI_H
#if defined(__cplusplus) // should test this macro in unix.
extern "C"
{
#endif
//macro define
#define LOGINFO_IP_LEN ((int)15)
#define LOGINFO_USER_LEN ((int)16)
#define LOGINFO_PWD_LEN ((int)16)
#define SGIP_NUMBER_LEN ((int)21)
#define SGIP_CORP_ID_LEN ((int)5)
#define SGIP_SERVICE_TYPE_LEN ((int)10)
#define SGIP_FEE_VALUE_LEN ((int)6)
#define SGIP_TIME_LEN ((int)16)
#define SGIP_MSG_LEN ((int)255)
#define SGIP_RESERVE_LEN ((int)8)
#define SGIP_DELIVER_MSG ((int)0)
#define SGIP_REPORT_MSG ((int)1)
// error code define
// 1, the errors that 'InitSgipAPI' function return
#define SGIP_INIT_SUCCESS ((int)0)
#define SGIP_INIT_AGAIN ((int)-1)
#define SGIP_INIT_PARA_NULL ((int)-2)
#define SGIP_INIT_OS_ERROR ((int)-3)
#define SGIP_INIT_APP_ERROR ((int)-4)
#define SGIP_INIT_PARA_ERROR ((int)-5)
#define SGIP_INIT_NET_ERROR ((int)-6)
// 2, the errors that 'SendMTMessage' function return, when error code > 0, they come from gw
#define SGIP_SEND_SUCCESS ((int)0)
#define SGIP_SEND_NO_INIT ((int)-1)
#define SGIP_SEND_PARA_NULL ((int)-2)
#define SGIP_SEND_PARA_ERROR ((int)-3)
#define SGIP_SEND_NO_NETLINK ((int)-4)
#define SGIP_SEND_SYSTEM_ERROR ((int)-5)
#define SGIP_SEND_GETRESULT_ERROR ((int)-6)
#define SGIP_SEND_MAKESEQNO_FAIL ((int)-10)
#define SGIP_SEND_SETTIMER_FAIL ((int)-11)
#define SGIP_SEND_SENDTONET_FAIL ((int)-12)
#define SGIP_SEND_RECVRSP_TIMEOUT ((int)-13)
// 3, the errors that 'RecvMessage' function return
#define SGIP_RECV_SUCCESS ((int)0)
#define SGIP_RECV_NO_INIT ((int)-1)
#define SGIP_RECV_PARA_NULL ((int)-2)
#define SGIP_RECV_PARA_ERROR ((int)-3)
#define SGIP_RECV_SYSTEM_LOCKERR ((int)-4)
#define SGIP_RECV_TIMEOUT_BACK ((int)-5)
#define SGIP_RECV_SYSTEM_ERROR ((int)-6)
// sturct define
#pragma pack( 1 )
typedef struct loginInfo_tag
{
unsigned int spNodeId; // sp node code, should be assigned by gw
char gwIp[LOGINFO_IP_LEN + 1];
int gwPort;
char loginGwUser[LOGINFO_USER_LEN + 1];
char loginGwPwd[LOGINFO_PWD_LEN + 1];
char appIp[LOGINFO_IP_LEN + 1]; // provide sgip server on the ip.
int appPort; // provide sgip server at the port
char gwLinkUser[LOGINFO_USER_LEN + 1]; // gw use the username to link app
char gwLinkPwd[LOGINFO_PWD_LEN + 1]; // gw use the password to link app
} LoginInfo;
typedef struct
{
unsigned int node;
unsigned int time;
unsigned int number;
} SequenceNo;
typedef struct
{
char pSpNumber[SGIP_NUMBER_LEN];
char pChargeNumber[SGIP_NUMBER_LEN];
char pUserNumber[SGIP_NUMBER_LEN];
char pCorpId[SGIP_CORP_ID_LEN];
char pServiceType[SGIP_SERVICE_TYPE_LEN];
unsigned char feetype;
char pFeeValue[SGIP_FEE_VALUE_LEN];
char pGivenValue[SGIP_FEE_VALUE_LEN];
unsigned char agentflag;
unsigned char morelatetomtflag;
unsigned char priority;
char pExpireTime[SGIP_TIME_LEN]; // user write format:"yymmddhhmmss"
char pScheduleTime[SGIP_TIME_LEN]; // user write format:"yymmddhhmmss"
unsigned char reportflag;
unsigned char tppid;
unsigned char tpudhi;
unsigned char msgcoding;
unsigned char msgtype;
unsigned int msglen;
char pContent[SGIP_MSG_LEN];
char pReserve[SGIP_RESERVE_LEN];
} Submit;
typedef struct
{
char pUserNumber[SGIP_NUMBER_LEN];
char pSpNumber[SGIP_NUMBER_LEN];
unsigned char tppid;
unsigned char tpudhi;
unsigned char msgcoding;
unsigned int msglen;
char pContent[SGIP_MSG_LEN];
char pReserve[SGIP_RESERVE_LEN];
} Deliver;
typedef struct
{
SequenceNo relationsn;
unsigned char reporttype;
char pUserNumber[SGIP_NUMBER_LEN];
unsigned char state;
unsigned char errcode;
char pReserve[SGIP_RESERVE_LEN];
} Report;
#pragma pack( ) // can't resume user's packing alignments.
// interface function
#ifdef WIN32 // only for windows
#ifndef UNIAPI_DLL
#define UNIAPI_DLL _declspec(dllimport)
#endif
#else
#ifndef UNIAPI_DLL
#define UNIAPI_DLL
#endif
#endif
// when compile with static lib
/*
#undef UNIAPI_DLL
#define UNIAPI_DLL
*/
UNIAPI_DLL int InitSgipAPI( char *path, LoginInfo *pLoginInfo );
UNIAPI_DLL int SendMTMessage( Submit *pMsg, SequenceNo *pMsgId );
UNIAPI_DLL int RecvMessage( int *piMsgType, void *pMsgBuf, int iBufSize );
#if defined(__cplusplus)
}
#endif
**********************************************************************************************
三个方法
InitSgipAPI
SendMTMessage
RecvMessage
通过C# invoke 调用。
//1. 初始化函数
[DllImport("UniAPIDll.dll", EntryPoint = "InitSgipAPI", CharSet = CharSet.Unicode)]
public static extern int InitSgipAPI(StringBuilder path, ref LoginInfo pLoginInfo);
//记录SP登录GW或者GW登录SP的登录信息结构
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct LoginInfo
{
public uint spNodeId; //sp的设备代码,应该由网关为其分配
[MarshalAs(UnmanagedType.ByValArray , SizeConst = 16)]
public char[] gwIp; //网关的侦听IP地址
public int gwPort; //网关的侦听端口
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public char[] loginGwUser; //sp登陆网关时所用的用户名
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public char[] loginGwPwd; //sp登陆网关时所用的密码
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public char[] appIp; //sp的侦听IP地址
public int appPort; //sp的侦听端口
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public char[] gwLinkUser; //网关登陆sp时所用的用户名
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public char[] gwLinkPwd; //网关登陆sp时所用的密码
}
private void button1_Click(object sender, EventArgs e)
{
LoginInfo ploginInfo = new LoginInfo();
ploginInfo.spNodeId = 3002300000;
ploginInfo.gwIp = " ".ToCharArray();
ploginInfo.gwPort = 9001;
ploginInfo.loginGwUser = " ".ToCharArray();
ploginInfo.loginGwPwd = " ".ToCharArray();
ploginInfo.appIp = " ".ToCharArray();
ploginInfo.appPort = 8000;
ploginInfo.gwLinkUser = " ".ToCharArray();
ploginInfo.gwLinkPwd = " ".ToCharArray();
string str = "D:\\我的文档\\Downloads\\dnntest\\WindowsFormsApplication2\\WindowsFormsApplication2\\bin\\Debug";
textBox1.Text = InitSgipAPI(str, ref ploginInfo).ToString();
}
InitSgipAPI总是报“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。 ”
--------------------编程问答-------------------- 用C#可以直接调用吗? --------------------编程问答-------------------- C# 到 c++ 参数 对照表
--------------------编程问答-------------------- C# 到 c++ 参数 对照表
--------------------编程问答-------------------- C# 调用 c++ 类型
注意:
为什么 有的要加 ref 为什么有的要用 char 有的要加 int 有的要用 ref int
一个 外国老 写的 国人 翻译了的
现在 找 不 到 了,自己找 --------------------编程问答-------------------- 两个问题:
1、结构体映射错误,正确做法:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi,Pack=1)]
public struct LoginInfo
{
public uint spNodeId; //sp的设备代码,应该由网关为其分配
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string gwIp; //网关的侦听IP地址
public int gwPort; //网关的侦听端口
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string loginGwUser; //sp登陆网关时所用的用户名
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string loginGwPwd; //sp登陆网关时所用的密码
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string appIp; //sp的侦听IP地址
public int appPort; //sp的侦听端口
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string gwLinkUser; //网关登陆sp时所用的用户名
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string gwLinkPwd; //网关登陆sp时所用的密码
}
2、函数字符集属性错误,正确做法:
--------------------编程问答-------------------- 两个问题:
[DllImport("UniAPIDll.dll", EntryPoint = "InitSgipAPI", CharSet = CharSet.Ansi)]
public static extern int InitSgipAPI(StringBuilder path, ref LoginInfo pLoginInfo);
1、结构体映射错误,正确做法:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi,Pack=1)]
public struct LoginInfo
{
public uint spNodeId; //sp的设备代码,应该由网关为其分配
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string gwIp; //网关的侦听IP地址
public int gwPort; //网关的侦听端口
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string loginGwUser; //sp登陆网关时所用的用户名
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string loginGwPwd; //sp登陆网关时所用的密码
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string appIp; //sp的侦听IP地址
public int appPort; //sp的侦听端口
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string gwLinkUser; //网关登陆sp时所用的用户名
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string gwLinkPwd; //网关登陆sp时所用的密码
}
2、函数字符集属性错误,正确做法:
--------------------编程问答--------------------
[DllImport("UniAPIDll.dll", EntryPoint = "InitSgipAPI", CharSet = CharSet.Ansi)]
public static extern int InitSgipAPI(StringBuilder path, ref LoginInfo pLoginInfo);
依然会包内存错误。。。我之前这样试过。。 --------------------编程问答--------------------
依然报错。 --------------------编程问答-------------------- [Quote=引用 6 楼 sdl2005lyx 的回复:]
sdl2005lyx
大侠,我之前这样写过,依然是报内存错误。。
--------------------编程问答-------------------- 用一个简单办法:在C++那边用sizeof,C#这边用Marshal.Sizeof,
对比两边的结构体大小是否一致! --------------------编程问答-------------------- 现在问题是,多种方法都试过了,依然是内存错误,有能真正执行通过的代码吗?
大小是一致的啊,里面有C的头文件。 --------------------编程问答-------------------- 如果这个dll跟硬件无关,你可以发给我:sdl2002lyx@163.com --------------------编程问答-------------------- 是要发短信吗? --------------------编程问答--------------------
恩,调用联通网关,合作接口。 --------------------编程问答--------------------
联通还要这样呀,学到了,电信是我们发送一些XML信息到,电信给的短信通道,我们提供短信内容,发送人等,电信负责发送
--------------------编程问答-------------------- 有始有终,真的没人知道吗? --------------------编程问答-------------------- 发短信,用webservice --------------------编程问答-------------------- lz,你会不会用VC,会的话,你直接用Vc写个测试程序。。。 --------------------编程问答-------------------- 需要用C#直接调用。。。
如果可以用VC就没问题了
DLL确定没有问题,是通用的。 --------------------编程问答-------------------- 这是我用VC写的测试程序,运行也有问题,你这样,不是有个Demo程序吗,
你发过来,我看看它是怎么使用的!
LoginInfo info;
info.spNodeId = 3002300000;
strcpy(info.gwIp ," ");
info.gwPort = 9001;
strcpy(info.loginGwUser, " ");
strcpy(info.loginGwPwd , " ");
strcpy(info.appIp , " ");
info.appPort = 8000;
strcpy(info.gwLinkUser , " ");
strcpy(info.gwLinkPwd, " ");
int size=sizeof(LoginInfo);
HMODULE hMod=LoadLibrary("UniAPIDll.dll");
typedef int (*FunAddr)(char* path, LoginInfo *pLoginInfo);
FunAddr fun = (FunAddr)GetProcAddress(hMod, "InitSgipAPI");
if(!fun)
{
MessageBox("获取函数地址失败!");
return FALSE;
}
int ret=fun("E:\\test\\ExamDlg",&info); //这里一样报错! --------------------编程问答-------------------- --------------------编程问答-------------------- 这个是通用的API接口,之前看到论坛上也有不少朋友在问,有调用成功的吗? --------------------编程问答-------------------- --------------------编程问答-------------------- 没有.net的调用接口么?
移动的都有,直接调用就行了
联通的如果是通用的,就比较麻烦了
需要把所有的数据类型重新定义以下。
c#才能使用定以后的函数。 --------------------编程问答-------------------- 很多时候C# 对于C或者C++的参数错误!LZ要仔细检查,这种问题麻烦 --------------------编程问答-------------------- 无语了,都是加油回复。。有大侠调试通过的吗? --------------------编程问答-------------------- 始终无法正常写LOG。。 --------------------编程问答-------------------- C#和C++参数类型对照表。
还想请教个问题,联通或移动的网关接口,个人有权限调用么? --------------------编程问答-------------------- 我现在也碰到这个问题,也几乎尝试了各种能想到的数据类型,还是不行。。。楼主问题解决了吗?怎么解决的? --------------------编程问答-------------------- 库跟你的也是一样的。。
补充:.NET技术 , C#