// 原型(C编写)
签名函数
int SEC_CliSign(unsigned char  *str,
int strl,
unsigned char  *sig,
int  *sigl,
char  *pin);
输入参数:
str,准备进行签名的数据
strl,准备进行签名的数据长度
pin, 智能卡或USBKey的密码(如果不要求每次签名输入密码,可省略该参数)
输出参数:
sig,数据签名+签名方安全介质名称
sigl,(数据签名+签名方安全介质名称)的长度
返 回 值:
SEC_SUCCESS,成功
其它,失败,错误代码另见
// 申明
// 请求交易上传结构(由于其他调用需要用到,必须这么申明)
public struct UpInfo
{
public string SignId;
public byte[] UpSign;
public byte[] XmlInfo;
}

public class LibWrap
{
// 客户端对交易报文签名函数
[DllImport("seccli.dll",EntryPoint="SEC_CliSign")]
public static extern int SEC_CliSign(
ref byte[] XmlInfo, 
int strLen,
out byte[] UpSign,
out int nSigLen
);
}


// call
// 上传结构
UpInfo UpInfo = new UpInfo(); UpInfo.SignId = "CLIENT";
UpInfo.UpSign = new byte[180];
UpInfo.XmlInfo = new byte[sendData.Length]; char[] _sendData = sendData.ToCharArray();//sendData 是接口传输的XML报文
for(int i=0;i<sendData.Length;i++)
{
UpInfo.XmlInfo[i] = (byte)_sendData[i];
}

// 返回代码
int retId = 0;

int strLen = UpInfo.XmlInfo.Length;
int nSigLen = UpInfo.UpSign.Length;

retId = LibWrap.SEC_CliSign(ref UpInfo.XmlInfo, strLen, out UpInfo.UpSign, out nSigLen);
按照以上方式编写程序,存在如下错误:
* Exception: ------------------------------------------------------------------
System.ApplicationException: 未将对象引用设置到对象的实例。 ---> System.NullReferenceException: 未将对象引用设置到对象的实例。
   at Sky.BankAgent.Assembly.CCB.LibWrap.SEC_CliSign(Byte[]& XmlInfo, Int32 strLen, Byte[]& UpSign, Int32& nSigLen)
   at Sky.BankAgent.Assembly.CCB.Rules.Send(String sendData)
   at Sky.BankAgent.Assembly.CCB.Rules.SignIn(String sendData)
   at Sky.BankAgent.Assembly.CCB.BankTransactor.SignIn(Boolean compel)
   at Sky.BankAgent.Assembly.CCB.BankTransactor.Transact(DataSet instructs)
   --- 内部异常堆栈跟踪的结尾 ---
   at Sky.BankAgent.Assembly.CCB.BankTransactor.Transact(DataSet instructs)请指出问题的原因,谢谢!

解决方案 »

  1.   

    Have a try![DllImport("seccli.dll",EntryPoint="SEC_CliSign")]
    public static extern int SEC_CliSign(
    [In,MarshalAs(UnmanagedType.LPArray)]
    byte[] XmlInfo,
    int strLen,
    [Out,MarshalAs(UnmanagedType.LPArray, SizeConst=180)]
    byte[] UpSign,
    ref int nSigLen
    );//call
    retId = LibWrap.SEC_CliSign( UpInfo.XmlInfo, strLen, UpInfo.UpSign, ref nSigLen);
      

  2.   

    按照"Knight94(愚翁) "的方式进行修改,还是报相同的错误。* Exception: ------------------------------------------------------------------
    System.ApplicationException: 未将对象引用设置到对象的实例。 ---> System.NullReferenceException: 未将对象引用设置到对象的实例。
       at Sky.BankAgent.Assembly.CCB.LibWrap.SEC_CliSign(Byte[] XmlInfo, Int32 strLen, Byte[] UpSign, Int32& nSigLen)
      

  3.   

    dll函数的参数是五个,你的c#声明是4个,当然不对[DllImport("seccli.dll",EntryPoint="SEC_CliSign")]
    public static extern int SEC_CliSign(
    [In,MarshalAs(UnmanagedType.LPArray)]
    byte[] XmlInfo,
    int strLen,
    [Out,MarshalAs(UnmanagedType.LPArray, SizeConst=180)]
    byte[] UpSign,
    ref int nSigLen,
    [Out,MarshalAs(UnmanagedType.LPArray)]
    byte[] pin);
      

  4.   

    其他先不看,你c得函数要加上__stdcall,vc默认识__cdcall.
      

  5.   

    Knight94(愚翁)多申明一个参数后,在CALL也会增加一个参数,我想应该申明为 string类型的.不过byte[]类型,我也试过,都报同样的错误:* Exception: ------------------------------------------------------------------
    System.ApplicationException: 未将对象引用设置到对象的实例。 ---> System.NullReferenceException: 未将对象引用设置到对象的实例。
       at Sky.BankAgent.Assembly.CCB.LibWrap.SEC_CliSign(Byte[] XmlInfo, Int32 strLen, Byte[] UpSign, Int32& nSigLen, Byte[] pin)
       at Sky.BankAgent.Assembly.CCB.Rules.Send(String sendData)还有其他办法可以试吗?就这个问题已经折腾我好几天啦。
      

  6.   

    to 多申明一个参数后,在CALL也会增加一个参数,我想应该申明为 string类型的.不过byte[]类型,我也试过,都报同样的错误:这是必须的,在C中是5个参数,你在c#中也应该写成5个。至于char*转换成什么,有很多种方法来试,
    例如:
    StringBuilder
    或者
    [In,MarshalAs(UnmanagedType.LPTStr )]
    string
      

  7.   

    superxiaomm(小美) 你的描述我不明白,现在是用C#调用C写的DLL,具体想法能在重述吗?
      

  8.   

    Knight94(愚翁)还是同样的错误
    * Exception: ------------------------------------------------------------------
    System.ApplicationException: 未将对象引用设置到对象的实例。 ---> System.NullReferenceException: 未将对象引用设置到对象的实例。
       at Sky.BankAgent.Assembly.CCB.LibWrap.SEC_CliSign(Byte[] XmlInfo, Int32 strLen, Byte[] UpSign, Int32& nSigLen, String pin)
    申明
    // 客户端对交易报文签名函数
    [DllImport("seccli.dll",EntryPoint="SEC_CliSign")]
    public static extern int SEC_CliSign(
    [In,MarshalAs(UnmanagedType.LPArray, SizeConst=3800)]
    byte[] XmlInfo, 
    int strLen,
    [Out,MarshalAs(UnmanagedType.LPArray, SizeConst=180)]
    byte[] UpSign,
    ref int nSigLen,
    [In,MarshalAs(UnmanagedType.LPTStr )]
    string pin
    );//CALL
    string pin = " ";retId = LibWrap.SEC_CliSign(UpInfo.XmlInfo, strLen, UpInfo.UpSign, ref nSigLen,pin);不知道哪里错了,其他地方申明和赋值都不变。
      

  9.   

    Knight94(愚翁)不知道是否有参考价值。
    #include <stdio.h>
    #include "teapi.h"
    #include "secmid.h"
    /*请求报文*/
    typedef struct person{    
        char cpOpid[20];
        char account[17];
        unsigned char info[40];
        unsigned char upSig[179];
    }PERSON;
    /*响应报文*/
    typedef struct resbuf{    
        char cpOpid[20];
        int  result;
    }RESBUF;void main(int argc, char **argv)
    {
    char JYM[]="cmfptx";   /* 交易码 */
    char ReqFile[500],EchoFile[500];
    PERSON reqbuf;              /* 发送到服务器的请求报文结构 */
    RES    resbuf;               /* 接收自服务器的响应报文结构 */
    int nRet = 0;
    int nSigLen = 0,nEncLen = 0;
    char account[16]; memset(&reqbuf,0,sizeof(reqbuf));
    memset(&resbuf,0,sizeof(resbuf));
    memset(ReqFile,0,sizeof(ReqFile));
    memset(EchoFile,0,sizeof(EchoFile));

    strcpy(reqbuf->cpOpid,"381200252");
    strcpy(reqbuf->info,"Important Privacy Information of Client");
    strcpy(account,"8596581462875362");
    ……
    /* 对info字段进行签名 */
    nRet = SEC_CliSign(reqbuf->info, sizeof(reqbuf->info), reqbuf->upSig, &nSigLen);
    if (nRet)
    {
    logmsg("签名失败\n");
    return;
    }
      

  10.   

    这是对方写DLL的给的调用例子。用C写的。
      

  11.   

    你实在不行,用vc.net包一层,做成类库供c#调用。
      

  12.   

    哦,知道你的意思,我还要试试!VC的参数申明和C的对应关系unsigned char以及指针一类的都和C#一样吗?对VC不是懂。
      

  13.   

    public static extern int SEC_CliSign(
    StringBuilder str,
    int strLen,
    StringBuilder UpSign,
    ref int nSigLen,
    StringBuilder pin
    );
      

  14.   

    我的意思就是要你在函数前面加上CALLBACK,vc的默认调用协议是__cdecl会与其他语言不兼容。
      

  15.   

    也就是int __stdcall SEC_CliSign(.....