+ -
当前位置:首页 → 问答吧 → 求C#调用联通短信网关UniAPIDll.dll的代码

求C#调用联通短信网关UniAPIDll.dll的代码

时间:2011-12-28

来源:互联网

已经查阅了好多文章,都没有最终成功的解决代码,哪位大侠可以发送下?
[email protected]

小弟感激不尽。

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总是报“尝试读取或写入受保护的内存。这通常指示其他内存已损坏。 ”

作者: drskysleep   发布时间: 2011-12-28

C# 到 c++ 参数 对照表

作者: tigerleq   发布时间: 2011-12-28

C# 到 c++ 参数 对照表

作者: tigerleq   发布时间: 2011-12-28

C# 调用 c++ 类型 
注意:
为什么 有的要加 ref 为什么有的要用 char 有的要加 int 有的要用 ref int 
一个 外国老 写的 国人 翻译了的
现在 找 不 到 了,自己找

作者: tigerleq   发布时间: 2011-12-28

两个问题:
1、结构体映射错误,正确做法:
C# code

  [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、函数字符集属性错误,正确做法:
C# code

  [DllImport("UniAPIDll.dll", EntryPoint = "InitSgipAPI", CharSet = CharSet.Ansi)]
  public static extern int InitSgipAPI(StringBuilder path, ref LoginInfo pLoginInfo);

作者: sdl2005lyx   发布时间: 2011-12-28

[Quote=引用 6 楼 sdl2005lyx 的回复:]

sdl2005lyx

大侠,我之前这样写过,依然是报内存错误。。

作者: drskysleep   发布时间: 2011-12-28

用一个简单办法:在C++那边用sizeof,C#这边用Marshal.Sizeof,

对比两边的结构体大小是否一致!

作者: sdl2005lyx   发布时间: 2011-12-28