不平衡堆栈问题

时间:2011-03-01 13:11:46

标签: c# c++ dll dllimport

感谢周五我在“c#Problems with repeat console.writeline commands”上提供的所有帮助。我发现我所有的问题都是由于:“PInvokeStackImbalance”。

  • 我在WIN7 64位上使用C#Express 机
  • 我调用的ftcjtag.dll是一个32位的c ++ dll。我有64位版本 这个dll可用。
  • 此dll可以在http://www.ftdichip.com/Support/SoftwareExamples/MPSSE/FTCJTAG/FTCJTAG_200.zip
  • 下载
  • 我刚开始编码c#,到目前为止我用Google搜索的所有内容让我感到困惑,而不是帮助我。我希望你能给我一些提示我的代码有什么不对,或者建议怎么做。

错误讯息:

  

PInvokeStackImbalance wurde erkannt。   消息:对PInvoke函数'WindowsFormsApplication1!WindowsFormsApplication1.Form1 :: JTAG_GetHiSpeedDeviceNameLocIDChannel'的调用使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;




namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        uint ftStatus = FTC_SUCCESS;
        //uint numHiSpeedDevices = 0; // 32-bit unsigned integer
        byte[] byteHiSpeedDeviceName = new byte[MAX_NUM_DEVICE_NAME_CHARS];
        byte[] byteHiSpeedDeviceChannel = new byte[MAX_NUM_CHANNEL_CHARS];
        string hiSpeedChannel = null;

        uint locationID = 0;
        //UInt32 locationID = 0;

        uint hiSpeedDeviceType = 1;
        //UInt32 hiSpeedDeviceType = 1;

        //uint clk_div = 0;
        uint numBytesReturned = 0;
        private enum HI_SPEED_DEVICE_TYPES// : uint
        {
            FT2232H_DEVICE_TYPE = 1,
            FT4232H_DEVICE_TYPE = 2
        };
        string hiSpeedDeviceName = null;
        IntPtr ftHandle = IntPtr.Zero;
        public string bPin2LowHighState { get; set; }

        private const string App_Title = "FT2232/FT4232 JTAG Device C# .NET Test Application";
        private const string Dll_Version_Label = "FT2232/FT4232 JTAG DLL Version = ";
        private const string Device_Name_Label = "Device Name = ";

        private const uint FTC_SUCCESS = 0;
        private const uint FTC_DEVICE_IN_USE = 27;
        private const uint TEST_LOGIC_STATE = 1;
        private const uint RUN_TEST_IDLE_STATE = 2;
        private const uint MAX_NUM_DEVICE_NAME_CHARS = 100;
        private const uint MAX_NUM_CHANNEL_CHARS = 5;
        private const uint MAX_NUM_DLL_VERSION_CHARS = 10;
        private const uint MAX_NUM_ERROR_MESSAGE_CHARS = 100;
        private const uint WRITE_DATA_BUFFER_SIZE = 65536;
        private const uint READ_DATA_BUFFER_SIZE = 65536;
        private const uint READ_CMDS_DATA_BUFFER_SIZE = 131071;

        byte[] WriteDataBuffer = new byte[WRITE_DATA_BUFFER_SIZE];
        byte[] ReadDataBuffer = new byte[READ_DATA_BUFFER_SIZE];

        public uint clockFrequencyHz = 0;

        FTC_INPUT_OUTPUT_PINS LowInputOutputPinsData;
        FTH_INPUT_OUTPUT_PINS HighInputOutputPinsData;
        FTC_LOW_HIGH_PINS LowPinsInputData;
        FTH_LOW_HIGH_PINS HighPinsInputData;

        //**************************************************************************
        // TYPE DEFINITIONS
        //**************************************************************************

        public struct FTC_INPUT_OUTPUT_PINS
        {
            public bool bPin1InputOutputState;
            public bool bPin1LowHighState;
            public bool bPin2InputOutputState;
            public bool bPin2LowHighState;
            public bool bPin3InputOutputState;
            public bool bPin3LowHighState;
            public bool bPin4InputOutputState;
            public bool bPin4LowHighState;
        }
        public struct FTH_INPUT_OUTPUT_PINS
        {
            public bool bPin1InputOutputState;
            public bool bPin1LowHighState;
            public bool bPin2InputOutputState;
            public bool bPin2LowHighState;
            public bool bPin3InputOutputState;
            public bool bPin3LowHighState;
            public bool bPin4InputOutputState;
            public bool bPin4LowHighState;
            public bool bPin5InputOutputState;
            public bool bPin5LowHighState;
            public bool bPin6InputOutputState;
            public bool bPin6LowHighState;
            public bool bPin7InputOutputState;
            public bool bPin7LowHighState;
            public bool bPin8InputOutputState;
            public bool bPin8LowHighState;
        }
        public struct FTC_LOW_HIGH_PINS
        {
            public bool bPin1LowHighState;
            public bool bPin2LowHighState;
            public bool bPin3LowHighState;
            public bool bPin4LowHighState;
        }
        public struct FTH_LOW_HIGH_PINS
        {
            public bool bPin1LowHighState;
            public bool bPin2LowHighState;
            public bool bPin3LowHighState;
            public bool bPin4LowHighState;
            public bool bPin5LowHighState;
            public bool bPin6LowHighState;
            public bool bPin7LowHighState;
            public bool bPin8LowHighState;
        }
        public struct FTC_CLOSE_FINAL_STATE_PINS
        {
            public bool bTCKPinState;
            public bool bTCKPinActiveState;
            public bool bTDIPinState;
            public bool bTDIPinActiveState;
            public bool bTMSPinState;
            public bool bTMSPinActiveState;
        }

        //**************************************************************************
        // FUNCTION IMPORTS FROM FTCJTAG DLL
        //**************************************************************************
        [DllImport("ftcjtag.dll", EntryPoint = "JTAG_GetDllVersion", CallingConvention = CallingConvention.Cdecl)]
        static extern uint GetDllVersion(byte[] pDllVersion, uint buufferSize);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetErrorCodeString(string language, uint statusCode, byte[] pErrorMessage, uint bufferSize);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetNumHiSpeedDevices(ref uint NumHiSpeedDevices);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetHiSpeedDeviceNameLocIDChannel(uint deviceNameIndex, byte[] pDeviceName, uint deviceNameBufferSize, ref uint locationID, byte[] pChannel, uint channelBufferSize, ref uint hiSpeedDeviceType);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_OpenHiSpeedDevice(string DeviceName, uint locationID, string channel, ref IntPtr pftHandle);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetHiSpeedDeviceType(IntPtr ftHandle, ref uint hiSpeedDeviceType);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_Close(IntPtr ftHandle);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_CloseDevice(IntPtr ftHandle, ref FTC_CLOSE_FINAL_STATE_PINS pCloseFinalStatePinsData);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_InitDevice(IntPtr ftHandle, uint clockDivisor);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_TurnOnDivideByFiveClockingHiSpeedDevice(IntPtr ftHandle);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_TurnOffDivideByFiveClockingHiSpeedDevice(IntPtr ftHandle);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_TurnOnAdaptiveClockingHiSpeedDevice(IntPtr ftHandle);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_TurnOffAdaptiveClockingHiSpeedDevice(IntPtr ftHandle);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_SetDeviceLatencyTimer(IntPtr ftHandle, byte timerValue);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetDeviceLatencyTimer(IntPtr ftHandle, ref byte timerValue);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetHiSpeedDeviceClock(uint ClockDivisor, ref uint clockFrequencyHz);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetClock(uint clockDivisor, ref uint clockFrequencyHz);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_SetClock(IntPtr ftHandle, uint clockDivisor, ref uint clockFrequencyHz);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_SetLoopback(IntPtr ftHandle, bool loopBackState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_SetHiSpeedDeviceGPIOs(IntPtr ftHandle, bool bControlLowInputOutputPins, ref FTC_INPUT_OUTPUT_PINS pLowInputOutputPinsData, bool bControlHighInputOutputPins, ref FTH_INPUT_OUTPUT_PINS pHighInputOutputPinsData);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GetHiSpeedDeviceGPIOs(IntPtr ftHandle, bool bControlLowInputOutputPins, out FTC_LOW_HIGH_PINS pLowPinsInputData, bool bControlHighInputOutputPins, out FTH_LOW_HIGH_PINS pHighPinsInputData);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_Write(IntPtr ftHandle, bool bInstructionTestData, uint numBitsToWrite, byte[] WriteDataBuffer, uint numBytesToWrite, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_Read(IntPtr ftHandle, bool bInstructionTestData, uint numBitsToRead, byte[] ReadDataBuffer, ref uint numBytesReturned, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_WriteRead(IntPtr ftHandle, bool bInstructionTestData, uint numBitsToWriteRead, byte[] WriteDataBuffer, uint numBytesToWrite, byte[] ReadDataBuffer, ref uint numBytesReturned, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_GenerateClockPulses(IntPtr ftHandle, uint numClockPulses);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_ClearCmdSequence();
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_AddWriteCmd(bool bInstructionTestData, uint numBitsToWrite, byte[] WriteDataBuffer, uint numBytesToWrite, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_AddReadCmd(bool bInstructionTestData, uint numBitsToRead, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_AddWriteReadCmd(bool bInstructionTestData, uint numBitsToWriteRead, byte[] WriteDataBuffer, uint numBytesToWrite, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_ExecuteCmdSequence(IntPtr ftHandle, byte[] ReadCmdSequenceDataBuffer, ref uint numBytesReturned);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_ClearDeviceCmdSequence(IntPtr ftHandle);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_AddDeviceWriteCmd(IntPtr ftHandle, bool bInstructionTestData, uint numBitsToWrite, byte[] WriteDataBuffer, uint numBytesToWrite, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_AddDeviceReadCmd(IntPtr ftHandle, bool bInstructionTestData, uint numBitsToRead, uint tapControllerState);
        [DllImport("ftcjtag.dll", CallingConvention = CallingConvention.Cdecl)]
        static extern uint JTAG_AddDeviceWriteReadCmd(IntPtr ftHandle, bool bInstructionTestData, uint numBitsToWriteRead, byte[] WriteDataBuffer, uint numBytesToWrite, uint tapControllerState);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            LowInputOutputPinsData.bPin1InputOutputState = true;    //true= Enable TCK, TMS and TDI outputs
            LowInputOutputPinsData.bPin2InputOutputState = false;
            LowInputOutputPinsData.bPin3InputOutputState = false;
            LowInputOutputPinsData.bPin4InputOutputState = false;
            LowInputOutputPinsData.bPin1LowHighState = false;       //false= Enable TCK, TMS and TDI outputs
            LowInputOutputPinsData.bPin2LowHighState = false;
            LowInputOutputPinsData.bPin3LowHighState = false;
            LowInputOutputPinsData.bPin4LowHighState = false;

            HighInputOutputPinsData.bPin1InputOutputState = false;
            HighInputOutputPinsData.bPin2InputOutputState = false;
            HighInputOutputPinsData.bPin3InputOutputState = false;
            HighInputOutputPinsData.bPin4InputOutputState = false;
            HighInputOutputPinsData.bPin5InputOutputState = false;
            HighInputOutputPinsData.bPin6InputOutputState = false;
            HighInputOutputPinsData.bPin7InputOutputState = false;
            HighInputOutputPinsData.bPin8InputOutputState = false;
            HighInputOutputPinsData.bPin1LowHighState = false;
            HighInputOutputPinsData.bPin2LowHighState = false;
            HighInputOutputPinsData.bPin3LowHighState = false;
            HighInputOutputPinsData.bPin4LowHighState = false;
            HighInputOutputPinsData.bPin5LowHighState = false;
            HighInputOutputPinsData.bPin6LowHighState = false;
            HighInputOutputPinsData.bPin7LowHighState = false;
            HighInputOutputPinsData.bPin8LowHighState = false;

            ftStatus = JTAG_GetHiSpeedDeviceNameLocIDChannel(0, byteHiSpeedDeviceName, MAX_NUM_DEVICE_NAME_CHARS, ref locationID, byteHiSpeedDeviceChannel, MAX_NUM_CHANNEL_CHARS, ref hiSpeedDeviceType);
            if (ftStatus != 0) error(Convert.ToInt32(ftStatus));
            hiSpeedChannel = Encoding.ASCII.GetString(byteHiSpeedDeviceChannel);// Trim strings to first occurrence of a null terminator character
            hiSpeedChannel = hiSpeedChannel.Substring(0, hiSpeedChannel.IndexOf("\0"));
            hiSpeedDeviceName = Encoding.ASCII.GetString(byteHiSpeedDeviceName);// Trim strings to first occurrence of a null terminator character
            hiSpeedDeviceName = hiSpeedDeviceName.Substring(0, hiSpeedDeviceName.IndexOf("\0"));// The ftHandle parameter is a pointer to a variable of type DWORD ie 32-bit unsigned integer

            ftStatus = JTAG_OpenHiSpeedDevice(hiSpeedDeviceName, locationID, hiSpeedChannel, ref ftHandle);
            if (ftStatus != 0) error(Convert.ToInt32(ftStatus));

            ftStatus = JTAG_InitDevice(ftHandle, 0);
            if (ftStatus != 0) error(Convert.ToInt32(ftStatus));

            ftStatus = JTAG_TurnOffDivideByFiveClockingHiSpeedDevice(ftHandle);
            if (ftStatus != 0) error(Convert.ToInt32(ftStatus));

            ftStatus = JTAG_SetClock(ftHandle, 6, ref clockFrequencyHz);
            if (ftStatus != 0) error(Convert.ToInt32(ftStatus));

            ftStatus = JTAG_SetHiSpeedDeviceGPIOs(ftHandle, true, ref LowInputOutputPinsData, true, ref HighInputOutputPinsData);
            if (ftStatus != 0) error(Convert.ToInt32(ftStatus));

        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        void error(int e)
        {
            switch (e)
            {
                case 0: Console.WriteLine("FTC_SUCCESS 0 // FTC_OK"); break;
                case 1: Console.WriteLine("FTC_INVALID_HANDLE"); break;
                case 2: Console.WriteLine("FTC_DEVICE_NOT_FOUND"); break;
                case 3: Console.WriteLine("FTC_DEVICE_NOT_OPENED"); break;
                case 4: Console.WriteLine("FTC_IO_ERROR"); break;
                case 5: Console.WriteLine("FTC_INSUFFICIENT_RESOURCES"); break;
                case 20: Console.WriteLine("FTC_FAILED_TO_COMPLETE_COMMAND"); break;
                case 21: Console.WriteLine("FTC_FAILED_TO_SYNCHRONIZE_DEVICE_MPSSE"); break;
                case 22: Console.WriteLine("FTC_INVALID_DEVICE_NAME_INDEX"); break;
                case 23: Console.WriteLine("FTC_NULL_DEVICE_NAME_BUFFER_POINTER"); break;
                case 24: Console.WriteLine("FTC_DEVICE_NAME_BUFFER_TOO_SMALL"); break;
                case 25: Console.WriteLine("FTC_INVALID_DEVICE_NAME"); break;
                case 26: Console.WriteLine("FTC_INVALID_LOCATION_ID"); break;
                case 27: Console.WriteLine("FTC_DEVICE_IN_USE"); break;
                case 28: Console.WriteLine("FTC_TOO_MANY_DEVICES"); break;
                case 29: Console.WriteLine("FTC_NULL_CHANNEL_BUFFER_POINTER"); break;
                case 30: Console.WriteLine("FTC_CHANNEL_BUFFER_TOO_SMALL"); break;
                case 31: Console.WriteLine("FTC_INVALID_CHANNEL"); break;
                case 32: Console.WriteLine("FTC_INVALID_TIMER_VALUE"); break;
                case 33: Console.WriteLine("FTC_INVALID_CLOCK_DIVISOR"); break;
                case 34: Console.WriteLine("FTC_NULL_INPUT_OUTPUT_BUFFER_POINTER"); break;
                case 35: Console.WriteLine("FTC_INVALID_NUMBER_BITS"); break;
                case 36: Console.WriteLine("FTC_NULL_WRITE_DATA_BUFFER_POINTER"); break;
                case 37: Console.WriteLine("FTC_INVALID_NUMBER_BYTES"); break;
                case 38: Console.WriteLine("FTC_NUMBER_BYTES_TOO_SMALL"); break;
                case 39: Console.WriteLine("FTC_INVALID_TAP_CONTROLLER_STATE"); break;
                case 40: Console.WriteLine("FTC_NULL_READ_DATA_BUFFER_POINTER"); break;
                case 41: Console.WriteLine("FTC_COMMAND_SEQUENCE_BUFFER_FULL"); break;
                case 42: Console.WriteLine("FTC_NULL_READ_CMDS_DATA_BUFFER_POINTER"); break;
                case 43: Console.WriteLine("FTC_NO_COMMAND_SEQUENCE"); break;
                case 44: Console.WriteLine("FTC_INVALID_NUMBER_CLOCK_PULSES"); break;
                case 45: Console.WriteLine("FTC_INVALID_NUMBER_SINGLE_CLOCK_PULSES"); break;
                case 46: Console.WriteLine("FTC_INVALID_NUMBER_TIMES_EIGHT_CLOCK_PULSES"); break;
                case 47: Console.WriteLine("FTC_NULL_CLOSE_FINAL_STATE_BUFFER_POINTER"); break;
                case 48: Console.WriteLine("FTC_NULL_DLL_VERSION_BUFFER_POINTER"); break;
                case 49: Console.WriteLine("FTC_DLL_VERSION_BUFFER_TOO_SMALL"); break;
                case 50: Console.WriteLine("FTC_NULL_LANGUAGE_CODE_BUFFER_POINTER"); break;
                case 51: Console.WriteLine("FTC_NULL_ERROR_MESSAGE_BUFFER_POINTER"); break;
                case 52: Console.WriteLine("FTC_ERROR_MESSAGE_BUFFER_TOO_SMALL"); break;
                case 53: Console.WriteLine("FTC_INVALID_LANGUAGE_CODE"); break;
                case 54: Console.WriteLine("FTC_INVALID_STATUS_CODE"); break;
                default: Console.WriteLine("FTC: Unknown error occured."); break;
            }
            System.Environment.Exit(-1);
        }
    }
}

2 个答案:

答案 0 :(得分:4)

自从我上次使用PInvoke以来已经有很长一段时间了但是我相信你的问题在于,正如错误消息所暗示的那样,你正在包装的DLL的调用约定。

快速查看FTCJTAG.dll的源代码显示所有方法都标记为WINAPI。这意味着他们使用stdcall调用约定。

您的C#代码通过告诉PInvoke使用cdecl调用约定来导入这些函数。

如果您不熟悉调用约定的概念,维基百科有一个不错的写作here

总结:您所调用的代码和DLL不同意如何发送彼此信息以及谁负责清理。您需要使用stdcall约定从dll导入函数。

答案 1 :(得分:0)

问题是你正在编译的是......如果你正在编译到x86那么你的32位dll将会工作,如果你编译为“任何cpu”我认为是默认的...你的代码将运行为64位,您将无法使用32位DLL ...将编译设置切换为x86或使用64位DLL。