c++中 有这样的方法
DWORD GetChallenge(IN HANDLE hContext,
                     IN WCHAR  *pszUserName,
                     OUT BYTE  **pChallenge, 
                     OUT DWORD *dwcbChallenge);
C#中我用下面的方法使用
[DllImport("cardmgr.DLL", SetLastError = true)]
        public static extern uint CMGetChallenge
            (
            IntPtr hContext,
            [MarshalAs(UnmanagedType.LPWStr)] string pwszUserName,
            ref byte[] pbChallenge,
            ref int cbChallenge);但是在 程序中运行时获取的pbChallenge不正确,以下是调用代码
 uint dwAcquireCardStatus = 1;
            uint dwLockCardStatus = 1;
            uint dwChangePinStatus = 0;
            IntPtr hContext = new IntPtr();
            int lenChallenge = 16;
            byte[] challenge = new byte[16];            dwAcquireCardStatus = CardMgrWrapper.CCAcquireSingleCard(ref hContext);
            if (dwAcquireCardStatus == 0)
            {
                dwLockCardStatus = CardMgrWrapper.CCLockCard(hContext, 0);
                if (dwLockCardStatus == 0)
                {
                    dwChangePinStatus = CardMgrWrapper.CMGetChallenge2(hContext,
                                                             SCUserType.Admin,
                                                             ref challenge,
                                                             ref lenChallenge
                                                             );
                }
                else
                {
                    dwChangePinStatus = dwLockCardStatus;
                }
            }
调用后 challenge 得到的值不正确请问 是不是我在DllImport后用C#写的参数不对?

解决方案 »

  1.   

    ref byte[] pbChallenge,//这里有问题 , c++ ** 是指向指针的指针它意思是要在dll开辟内存,不能用ref ,  try out
      

  2.   

    谢谢 hdt(倦怠) 兄
    [DllImport("cardmgr.DLL", SetLastError = true)]
            public static extern uint CMGetChallenge
                (
                IntPtr hContext,
                [MarshalAs(UnmanagedType.LPWStr)] string pwszUserName,
                [Out] byte[] pbChallenge,
                ref int cbChallenge);
    我改成上面的签名后
    在调用时pbChallenge的值有改变了,但是pbChallenge中只有前3个有值其他的都是0,正常情况下应该全部都有值。
    如果 把[Out] byte[] pbChallenge 改成out byte[] pbChallenge,则pbChallenge中没有任何值。
      

  3.   

    直接把ref 或者 out去掉应该可以...byte[]在C#里面访问的时候应该就是用首地址,如果再指定ref的话......明白?
      

  4.   

    给你个例子
    c++ dll 
    int TestRefArrayOfInts(int** ppArray, int* pSize);
    C# 申明
    [ DllImport( "..\\LIB\\PinvokeLib.dll" )]
     public static extern int TestRefArrayOfInts( ref IntPtr array, 
          ref int size );
    调用
     int[] array2 = new int[ 10 ];
          int size = array2.Length;
          Console.WriteLine( "\n\nInteger array passed ByRef before call:" );
          for( int i = 0; i < array2.Length; i++ )
          {
             array2[ i ] = i;
             Console.Write( " " + array2[ i ] );
          }
          IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( size ) 
             * array2.Length );
          Marshal.Copy( array2, 0, buffer, array2.Length );
          
          int sum2 = TestRefArrayOfInts( ref buffer, ref size );
          Console.WriteLine( "\nSum of elements:" + sum2 );
          if( size > 0 )
          {
             int[] arrayRes = new int[ size ];
             Marshal.Copy( buffer, arrayRes, 0, size );
             Marshal.FreeCoTaskMem( buffer );
             Console.WriteLine( "\nInteger array passed ByRef after call:" );
             foreach( int i in arrayRes )
             {
                Console.Write( " " + i );
             }
          }
          else
             Console.WriteLine( "\nArray after call is empty" );
      

  5.   

    to: tisocoff()
    你的方法 我已经试过了 行不通。
    to:hdt(倦怠) 
    我试试修改看。
      

  6.   

    to:hdt(倦怠) 
    多谢老兄了 我按照你给的例子改完后可以正常工作了。以下是代码:
     [DllImport("cardmgr.DLL", SetLastError = true)]
            public static extern uint CMGetChallenge
                (
                 IntPtr hContext,
                [MarshalAs(UnmanagedType.LPWStr)] string pwszUserName,
                ref IntPtr pbChallenge,
                ref int cbChallenge);
    调用代码:
     IntPtr hContext = new IntPtr();
                int lenChallenge = 8;
               
                IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf( lenChallenge ));            /* Acquire the card context -----------------------------------------*/
                dwAcquireCardStatus = CardMgrWrapper.CCAcquireSingleCard(ref hContext);
                if (dwAcquireCardStatus == 0)
                {
                    /* Lock the card to begin a transaction --------------------------*/
                    dwLockCardStatus = CardMgrWrapper.CCLockCard(hContext, 0);
                    if (dwLockCardStatus == 0)
                    {
                        dwChangePinStatus = CardMgrWrapper.CMGetChallenge(hContext,
                                                                 SCUserType.Admin,
                                                                 ref buffer,
                                                                 ref lenChallenge
                                                                 );
                    }
                    else
                        // pass on the LockCard failed error code to be returned.
                        dwChangePinStatus = dwLockCardStatus;
                }
                else
                    // pass on the AcquiredSingleCard failed error code to be returned.
                    dwChangePinStatus = dwAcquireCardStatus;            /* Unlock the card --------------------------------------------------*/
                if (dwLockCardStatus == 0)
                    CardMgrWrapper.CCUnlockCard(hContext, 0);            /* Release the card -------------------------------------------------*/
                if (dwAcquireCardStatus == 0)
                    CardMgrWrapper.CCReleaseCard(hContext);
                if (dwChangePinStatus != 0)
                {
                    throw new Exception(string.Format("Error:{0} HEX:{1}", dwChangePinStatus, Convert.ToString(dwChangePinStatus, 16)));
                }
                byte[] arrayRes = new byte[lenChallenge];
                Marshal.Copy(buffer, arrayRes, 0, lenChallenge);
                Marshal.FreeCoTaskMem(buffer);
                string challenge = "";
                foreach (byte b in arrayRes)
                {
                    challenge += Convert.ToString(b, 16);
                }