C#指针指向来自C+的非托管数据+;CLI项目 我有一个用C++编写的SDK,它管理一个设备。我控制设备的程序是用C#编写的,因此CLI包装类自然会在两种语言之间进行转换。我的C#项目将包装器作为DLL包含 我的问题是C++ SDK使用指针指向数据数组。这些指针在包装器中也可用

C#指针指向来自C+的非托管数据+;CLI项目 我有一个用C++编写的SDK,它管理一个设备。我控制设备的程序是用C#编写的,因此CLI包装类自然会在两种语言之间进行转换。我的C#项目将包装器作为DLL包含 我的问题是C++ SDK使用指针指向数据数组。这些指针在包装器中也可用,c#,visual-studio,c++-cli,clr,C#,Visual Studio,C++ Cli,Clr,包装器.cpp代码: Wrapper::Wrapper() { myData = new DataAquis(); //initiate C++ class's instance } int Wrapper::Start() { //(..) int num = myData->Start(); ptr = (myData->img); return num; } int DataAquis::Start() { // (...)

包装器.cpp代码:

Wrapper::Wrapper()
{
    myData = new DataAquis(); //initiate C++ class's instance
}

int Wrapper::Start()
{
    //(..)
    int num = myData->Start();
    ptr = (myData->img);
    return num;
}
int DataAquis::Start()
{
    // (...)
    // Pointer from SDK
    img = pBuffer;
    // (...)
    return FAILED(nError) ? -1 : 0;
}
此代码初始化设备并创建指向数据结构(无符号字符数组)的指针

包装器SDK.cpp代码:

Wrapper::Wrapper()
{
    myData = new DataAquis(); //initiate C++ class's instance
}

int Wrapper::Start()
{
    //(..)
    int num = myData->Start();
    ptr = (myData->img);
    return num;
}
int DataAquis::Start()
{
    // (...)
    // Pointer from SDK
    img = pBuffer;
    // (...)
    return FAILED(nError) ? -1 : 0;
}
包装器.h代码:

public ref class Wrapper
{
    public:
        Wrapper();

        // (...)
        unsigned char *ptr;

    private:
        // (...)
};
代码C#:

公共静态包装器myDataAqui;
// (...)
私有静态void DataAquisition()
{
//在包装器中调用start函数
myDataAqui.Start();
//指针使用的不安全代码
不安全的
{
//指向已获取的数据
字节*imgptr1=myDataAqui.ptr;
//AccesViolationException位于上一行。
//数据处理
对于(y=0;y<256;y++)
{
对于(x=0;x<320;x++)
{
内部温度=x*256+255-y;
Spectrum1.X_Data_brut[bufferIndex][temp]=(UInt16)(*imgptr1++++*imgptr1++*256);
aquirData[temp]=Spectrum1.X_Data_brut[bufferIndex][temp];
}
}
// (...)
}
}
如图所示,AccessViolationException在我将包装器指针转换为本地字节指针的那一行触发

如果我在那一行上放置一个断点,我可以看到包装器指针正确地指向内存地址,但表示它无法读取内存,因此指向的数据永远不会在C#中收集

我已经知道C++中的一个无符号字符的C等价物是一个字节,所以通常我应该读取相同数量的数据,并且永远不要超出数据结构的边界。 可能有用的其他信息:

  • 此项目已从另一台电脑上复制,并且同一代码在该电脑上运行
  • 两台电脑都有相同的Visual Studio、相同的.Net版本、相同的SDK,都是64位编译的。只有Windows版本不同(在Windows 8上工作而不在Windows 7上工作)
  • 我尝试使用封送处理函数失败

你有办法解决这个问题吗

我不确定为什么会出现异常,但我会在C++/CLI端将其封送到CLR数组中,这样在C#端就不需要不安全的代码

C++/CLI:

#include <vcclr.h>
#include <algorithm>

#pragma unmanaged

const int data_size = 100;

unsigned char * foo()
{
    auto p = new unsigned char[data_size];
    for (int i = 0; i < data_size; ++i)
        p[i] = (unsigned char)i;
    return p;
}

#pragma managed

public ref class Wrapper
{
public:
    array<unsigned char>^ data;

    void Start()
    {
        auto p = foo();
        data = gcnew array<unsigned char>(data_size);
        pin_ptr<unsigned char> data_pin = &data[0];
        std::copy(p, p+data_size, (unsigned char *)data_pin);
    }
};

这将包含靠近源代码的任何可能的问题,并使调试不那么混乱。如果它在STD中崩溃:复制,那么你只是使用C++对象错误。p> 所以,人们来这里只是为了投反对票,或者他们真的有什么想法吗?是的,我不明白——有人也喜欢为C++/CLI Q出主意。你能给我们看一下“ptr”的声明吗?我想知道如果你的包装需要一个PixPtri网编辑我的问题,如果我理解正确,我只是直接分配内存在C++中,创建一个C++的数据结构,直接从C?我想知道为什么我以前没有想到这一点!但是,#pragma managed/unmanaged#的目的是什么?#pragma managed/unmanaged允许在单个编译单元中同时包含托管和非托管代码。我只是在这里使用它来清楚地显示FoE()是非托管代码。对,我正在分配一个托管数组,并将数据从本地C++堆复制到其中。然后C#代码只处理托管对象,如果某个对象发生故障,它将立即失败。是的,它成功了,很抱歉,我还没有接受答案。