3

请看下面的头文件

#pragma once
using namespace UsbLibrary;

ref class MissileLauncher
{
public:
    MissileLauncher(void);

private:
    //Bytes used in command
    unsigned char UP[10];
    unsigned char RIGHT[10];
    unsigned char LEFT[10];
    unsigned char DOWN[10];

    unsigned char FIRE[10];
    unsigned char STOP[10];
    unsigned char LED_OFF[9];
    unsigned char LED_ON[9];

    UsbHidPort USB;
};

我在 Visual Studio Professional 2010 中使用 Visual C++ 项目(C++/CLI?)。运行此代码时,出现很多错误

Error   1   error C4368: cannot define 'UP' as a member of managed 'MissileLauncher': mixed types are not supported 
Error   2   error C4368: cannot define 'RIGHT' as a member of managed 'MissileLauncher': mixed types are not supported  
Error   3   error C4368: cannot define 'LEFT' as a member of managed 'MissileLauncher': mixed types are not supported   
Error   4   error C4368: cannot define 'DOWN' as a member of managed 'MissileLauncher': mixed types are not supported   
Error   5   error C4368: cannot define 'FIRE' as a member of managed 'MissileLauncher': mixed types are not supported   
Error   6   error C4368: cannot define 'STOP' as a member of managed 'MissileLauncher': mixed types are not supported   
Error   7   error C4368: cannot define 'LED_OFF' as a member of managed 'MissileLauncher': mixed types are not supported    
Error   8   error C4368: cannot define 'LED_ON' as a member of managed 'MissileLauncher': mixed types are not supported 

在这里,命名空间USBLibrary来自 C# dll 文件。UsbHidPort;是来自该 C# dll 的对象

那么,为什么我会收到此错误?有任何想法吗?

4

2 回答 2

8

在这种特定情况下,这实际上不是问题,至少从可见的情况来看,但 C++/CLI 编译器会试图阻止您以导弹式的方式射击您的腿。垃圾收集器在压缩堆时移动对象。这使得本机对象非常危险,任何指向它们的指针都将变为无效并在您写入它们时会破坏 GC 堆。收集器无法更新这些指针,它找不到它们。风险太高,所以编译器只是禁止它。

另一种方法是将这些成员声明为指针,并在类构造函数中使用 operator new 分配数组。

private:
    unsigned char* UP;
    // etc..
public:
    MissileLauncher() {
        UP = new unsigned char[10];
        // etc..
    }
    ~MissileLauncher() {
        this->!MissileLauncher();
        UP = nullptr;   // Destructor may be called more than once 
    }
    !MissileLauncher() {
        delete[] UP;
        // etc...
    }

请注意析构函数和终结器释放这些数组的内存的要求。定义析构函数也带来了客户端程序员必须调用它的负担(Dispose() 或在 C# 客户端程序中使用,在 C++/CLI 程序中删除或堆栈语义),为这么小的分配跳过它并非不合理. 最后但并非最不重要的一点是,考虑理智的解决方案并使用托管数组:

private:
    array<Byte>^ UP;
    // etc..
public:
    MissileLauncher() {
        UP = gcnew array<Byte>(10);
        // etc..
    }
于 2013-05-10T23:41:16.117 回答
1

问题是您混合了托管和非托管类型,这就是编译器警告的含义。该类是托管类,但整数数组算作非托管对象。这会导致垃圾收集出现问题。在这里阅读所有相关信息:

http://blogs.msdn.com/b/branbray/archive/2005/07/20/441099.aspx

为什么不使用托管数组?

于 2013-05-10T20:30:51.687 回答