获得错误,对PInvoke函数的调用使堆栈失衡

时间:2012-12-20 17:42:16

标签: c# visual-studio-2010 visual-c++ dll dllimport

我编写了以下C++代码来创建win 32 Dynamic link library

#include <windows.h>
#include <some.h>

unsigned char  m_KSN[10];
unsigned char m_inintial_key[16];
unsigned char initial_key[16];

extern "C" __declspec(dllexport) unsigned char* OnDecryption(LPCTSTR stringKSN, 
    LPCTSTR BDK){
        for( i=0;i<10;i++){
            m_KSN[i]=asctohex(stringKSN[2*i],stringKSN[2*i+1]); } 
        for( i=0;i<16;i++){
    m_inintial_key[i]=asctohex(BDK[2*i],BDK[2*i+1]);}
       GetInitalKey(m_KSN, m_inintial_key, initial_key);
       // GetInitialKey function written in `.lib` file. Data type of (Byte*a Byte*    b Byte* c) 
   return initial_key;
  }

我的C#代码在哪里:

static class DecryptionDll
{
  public String BDK = "0111111119ABCDEFFEDCBA9877777777";
  public String KSN = "62994900380000C00329";

  internal static class UnsafeNativeMethods
    {   
        const string _dllLocation = "finalTest.dll";
        [DllImport(_dllLocation)]
        public static extern byte OnDecryption(string ksn, String bdk);
     }
}

我把dll文件放在我当前的目录中,我得到了以下命令:

String path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.
GetExecutingAssembly().Location);

它显示我my debug文件夹是当前路径。所以我把dll放在那里。我也有很多帖子,但无法理解PInvoke情况。 请帮帮我..

请告诉我应该在c++c#代码中进行哪些更改,以调用dll中编写的方法。

对于这么多的编辑,我感到非常抱歉。这是因为我的连接速度缓慢

1 个答案:

答案 0 :(得分:0)

您的C ++函数被声明为返回指向unsigned char数据的指针,但从不返回任何内容。令人惊讶的是它编译;鉴于该声明以及没有“return”语句的事实,您似乎应该从C ++编译器中收到错误。

我猜你的意思是返回m_KSN的地址,但声明的变量在哪里?从命名,它看起来像一个成员变量,但该函数似乎不是一个成员函数。

修改后,事情仍然没有排成一行。名称中有很多带有m_的变量,这意味着它们是成员变量。但是没有课程存在,我们也没有看到这些变量的声明。

在C#中,您声明函数返回单个字节。你正在从C ++返回一个指向字节的指针,这通常意味着你要返回一个完整的字节数组。您的C#声明应该更像这样吗?

public static extern byte [] OnDecryption(string ksn, String bdk);

您的C ++代码假定传递的字符串的长度,并且从不测试它们。您可能会进入一个空字符串,或者比您想象的更短(或更长)的字符串。或者是没有有效十六进制字符的字符串。

您能否与我们分享为什么您特别相信您的“功能不平衡堆栈”?你的意思是什么意思?

我看到你做了一些进一步的编辑,它解决了你之前使用的m_数组背后的谜团 - 尽管你有两个相同的m_initial_key声明变量。 m_ninitial_key是否与m_inintial_key在本质上不同,或者是一个错字?

但其他问题和疑问仍然存在。我想还有一个关于GetInitialKey()函数的问题。它不是一个众所周知的Windows功能,所以如果没有它的源代码,我们无法猜测它的作用;也许它期望参数不同于你传递它并且实际上导致问题。

由于您想要返回指向unsigned char数组的指针,您可以使用IntPtr执行此操作。在使用C#返回IntPtr后,使用Marshal.Copy函数将数据复制到byte []数组中。这一切看起来像这样:

    internal static class UnsafeNativeMethods
    {
        const string _dllLocation = "..\\..\\..\\FinalTest\\debug\\finalTest.dll";
        [DllImport(_dllLocation, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        public static extern IntPtr OnDecryption(string ksn, String bdk );

        static public byte[] OnDecryptionWrapper(string ksn, string bdk)
        {
            byte[] data = new byte[10];
            IntPtr ptr = OnDecryption(ksn, bdk);

            Marshal.Copy(ptr, data, 0, 10);
            return data;
        }
    }