当前位置:编程学习 > C#/ASP.NET >>

C++/CLI 调用 C DLL ,错误:此Bug常见来源包括用户对 COM-interope 或 Pinvoke的封送处理,这些错误可能会损坏堆栈

背景介绍:

     现有 C 和 C ++ 的混合代码,我要用 C++/CLI 去调用它,考虑到语言的差异,所以要将前者封装成 DLL。

     C 函数原型:

     int fb_data_send_Me(omap_usb_handle *usb, const void *data, unsigned size, unsigned count);

    该函数的作用是往指定的 usb 对象中写入 data ,data 的长度是 size,count 是写的次数;

     其中:fb_data_send_Me 第一句代码是这样的:

     unsigned  char* ptr = (unsigned char*) data;   // 可见传递的是 unsigned char 类型数组; c++/cli pinvoke C dll 封送处理 --------------------编程问答-------------------- 我的处理方法:

      我尝试了三种方法在 C++/CLI 中对 fb_data_send_Me进行声明:

      声明式样一:

      int fb_data_send_Me( UsbDriver^ usb, System::IntPtr data, unsigned int size, unsigned int count); 

     声明样式二:

     int fb_data_send_Me( UsbDriver^ usb,
                        [MarshalAs(UnmanagedType::LPArray,SizeParamIndex = 1)]

                         array< byte >^ data,
                         unsigned int s ize,
                         unsigned int count );                                                                                     声明式样三:                                                                                                                                              int fb_data_send_Me( UsbDriver^ usb, array<byte>^ data, unsigned int size, unsigned int count); --------------------编程问答-------------------- 对于声明一的调用方式:

   int total      = 1;
   int size       = 0;
   int writeTotal = 0;      // 存储实际写入的数据量;

  array< System::IntPtr >^ ptBuffer = gcnew array< System::IntPtr >( total );

size  = System::Runtime::InteropServices::Marshal::SizeOf( buffer[0] ) * buffer->Length;  
// 获取数组大小,buffer 为已经被填充的,即将传递下去的字节数组;

ptBuffer[0] = System::Runtime::InteropServices::Marshal::AllocHGlobal( size );                  // 分配非托管内存,到时候要手动释放;

 System::Runtime::InteropServices::Marshal::Copy( buffer,0,(System::IntPtr)ptBuffer[0],buffer->Length );  // 复制托管数组到非托管内存;
//
// 使用复制内存的方法,并且使用 drv_usb 对象,NG;
// 
writeTotal = fb_data_send_Me( drv_usb, ( System::IntPtr )ptBuffer[0], (unsigned int)buffer->Length, (unsigned int)0 );  --------------------编程问答-------------------- 程序报告错误,截图如下:
--------------------编程问答-------------------- 第一个参数可能就错了
omap_usb_handle 类型是托管的还是非托管的,如果是非托管的不能用^ --------------------编程问答-------------------- 对于方式二的引用:

   writeTotal =  fb_data_send_Me( drv_usb,buffer, (unsigned int)buffer->Length, (unsigned int)0 ));


   其中:buffer 为已经填充 Ok 的unsigned char 星字节数组。

    编译还是报告相同的错误。 --------------------编程问答-------------------- 第一个参数是个抽象类,其源代码是这样子的:

class ComDriver
{
public:
    virtual ~ComDriver() { };
    virtual S8 open(U8 port, U32 baudRate, U8 parity, U8 stopBits, U8 data) = 0;
    virtual S8 close(void) = 0;
    virtual S8 reset(void) = 0;
    virtual S8 configure(U32 baudRate, U8 parity, U8 stopBits, U8 data) = 0;
    virtual S32 write(U8 *buffer, U32 size) = 0;
    virtual S32 read(U8 *buffer, U32 size, U32 timeout) = 0;
    virtual void registerCallback(T_COM_DRV_CALL_BACK callback) = 0;
    virtual void unregisterCallback() = 0;
    virtual void registerConnectionLostCallback(T_COM_DRV_CONNECTION_LOST_CALL_BACK callback) = 0;
    virtual U16 sid() = 0;
    virtual int getDrvErr() = 0;

protected:
    U8 debugLevel;
    virtual U8 initDebugLevel();
    virtual void debugPrint(U8 level, const char *format, ...);
}; --------------------编程问答-------------------- 之后有一个类 usbdriver 继承了该类,其具体如下:

class API UsbDriver : public ComDriver
{
public:
UsbDriver(U16 sid = 0);
    ~UsbDriver();
    S8 open(U8 port, U32 baudRate, U8 parity, U8 stopBits, U8 data);
    S8 close(void);
    S8 reset(void);
    S8 configure(U32 baudRate, U8 parity, U8 stopBits, U8 data);
    S32 write(U8 *buffer, U32 size);
    S32 read(U8 *buffer, U32 size, U32 timeout);
    void registerCallback(T_COM_DRV_CALL_BACK callback);
    void unregisterCallback();
    void registerConnectionLostCallback(T_COM_DRV_CONNECTION_LOST_CALL_BACK callback);
U16 sid() { return sessionId; }
int getDrvErr() { return driverErr; }
// 
// 手动添加测试;
//
int add( int x,int y );
private:
    U8 portNum;
    U16 sessionId, threadId;
    bool isOpen;
    bool isClosing;
    bool rxComplete;
    U8 *readFifo;
    U32 readFifoPtr;
    U32 readFifoBytesAvailable;
    HANDLE usbDevice;
    HANDLE listener;
    HANDLE readyEvent;
    HANDLE shutdownEvent;
char driverName[50];
int driverErr;
    unsigned char bulkInPipe;
unsigned char bulkOutPipe;

WINUSB_INTERFACE_HANDLE winUsbHandle;
   
T_COM_DRV_CALL_BACK rxCallback;
    T_COM_DRV_CONNECTION_LOST_CALL_BACK connectionLostCallback;  
HANDLE getDeviceHandle(U8 port);
void getDriverName(char deviceKeyName[]);
void getDeviceKeyName(char usbPath[], char deviceKeyName[]);
    S32 readHw(U8 *buffer, U32 size, U32 timeout);

// to use for WinUSB
bool initializeDevice();

    friend unsigned int __stdcall usbListener(void *drvObj);
};

我在进行封送的时候,在C++/CLI 中重构了  usbdriver 的所有变量,在程序跟踪时发现所有的变量都被赋值了,这个可能没错吧。

还是感谢以上的回答。

我明天尝试一下奉送 comdriver  这个抽象类试试 --------------------编程问答-------------------- 没仔细看,你使用c++/cli啊,他可以直接调用非托管dll,而不要像C#那样还要自己再封装一下 --------------------编程问答-------------------- 你好 问下这个问题解决了么 我也是报的同样的错误,在C#中调用了C++的代码,导致堆栈出错。但是对封装、封送知识还不大了解,嫩那个不能赐教下。多谢多谢
补充:.NET技术 ,  其他语言
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,