如何将IntPtr转换为本机directx11结​​构?

时间:2018-04-17 00:04:09

标签: c# c++ pinvoke direct3d slimdx

我试图在c ++中创建(并填充)D3D11Buffer,通过interop将指针传递给缓冲区内存到c#,以便使用slimdx从缓冲区读取 - 没有通过cpu的缓冲区副本应该是参与。

这是我目前的代码

功能导出:

extern "C" {__declspec(dllexport) HRESULT getValues(int * debug, ID3D11Buffer* bufOut); }

和功能:

ID3D11Device* d3d11Device;
ID3D11Buffer* triangleVertBuffer;
ID3D11DeviceContext* d3d11DevCon;

struct Vertex    //Overloaded Vertex Structure
{
    Vertex() {}
    Vertex(float x, float y, float z)
        : pos(x, y, z) {}

    XMFLOAT3 pos;
};

HRESULT getValues(int * debug, ID3D11Buffer* bufOut) {


    //Create the vertex buffer
    Vertex v[] =
    {
        Vertex(0.0f, 0.5f, 0.5f),
        Vertex(0.5f, -0.5f, 0.5f),
        Vertex(-0.5f, -0.5f, 0.5f),
    };

    D3D_FEATURE_LEVEL  FeatureLevelsRequested = D3D_FEATURE_LEVEL_11_0;
    UINT               numLevelsRequested = 1;
    D3D_FEATURE_LEVEL  FeatureLevelsSupported;

    //create device
    hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG, &FeatureLevelsRequested, numLevelsRequested, D3D11_SDK_VERSION, &d3d11Device, &FeatureLevelsSupported, &d3d11DevCon);
    debug[0] = hr;

    D3D11_BUFFER_DESC vertexBufferDesc;
    ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));

    vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexBufferDesc.ByteWidth = sizeof(Vertex) * 3;
    vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexBufferDesc.CPUAccessFlags = 0;
    vertexBufferDesc.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA vertexBufferData;


    ZeroMemory(&vertexBufferData, sizeof(vertexBufferData));
    vertexBufferData.pSysMem = v;
    hr2 = d3d11Device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &triangleVertBuffer);


    bufOut = triangleVertBuffer;

    debug[1] = hr2;

    return hr;
}
在C#中,我导入了这样的函数:

[System.Runtime.InteropServices.DllImport("CreateID3D11Buffer.dll", CallingConvention = CallingConvention.StdCall)]
    private static unsafe extern UInt32 getValues([In, Out] int[] debug, [In, Out] IntPtr bufIn);

然后这样称呼它:

int[]debug = new int[2];
IntPtr bufPtr;// = IntPtr.Zero;
UInt32 hr = getValues(debug, bufPtr);
DataStream ds = new DataStream(bufPtr, sizeof(Vector3) * 3, true, false);

到目前为止一直很好....现在我的问题(忍受我,仍然是c ++初学者和c#中间......):

  • 它不起作用:在c#中,最后一行DataStream构造函数抛出错误,因为 bufPtr ,IntPtr到非托管内存,为null。所以,显然,我的p / invoke或我的c ++代码中出现了问题......因此,我在c ++中查看了dx11函数的结果 - >
  • HRESULT:我在c#中的导入函数的返回值 hr 等于0,但 debug 数组中的两个元素都等于-1!一方面,我不明白如何解释负值,另一方面,返回值 hr 应该至少等于 debug [0] (我知道他们的类型不同)?所以,我不知道该怎么做,但它表明函数 D3D11CreateDevice()存在问题,然后(理解)也与 d3d11Device-&gt ; CreateBuffer()的。
  • 我不确定我是否正确理解了slimdx的DataStream构造函数 - IntPtr到非托管内存指向图形内存,或者这是一个从非托管cpu内存读取的函数?遗憾的是,我找不到使用IntPtr重载的任何示例...这里是doc:https://slimdx.org/docs/html/M_SlimDX_DataStream__ctor_2.htm

那么,我做错了吗? :)如果是这样,请指出我正确的方向。

注意:大多数cpp代码都是从https://www.braynzarsoft.net/viewtutorial/q16390-4-begin-drawing

中提取的

感谢您提供任何帮助/提示,​​一直试图解决这个问题。

1 个答案:

答案 0 :(得分:1)

ID3D11Buffer*是一个指针。如果你想返回一个指针,你必须传递指针指针,所以定义你的C ++方法如下:

HRESULT getValues(int * debug, ID3D11Buffer** bufOut)
{
    ...

    *bufOut = triangleVertBuffer;

    ...
}

和C#这样:

[DllImport("CreateID3D11Buffer.dll", CallingConvention = CallingConvention.StdCall)]
private static extern int getValues([In, Out] int[] debug, out IntPtr bufIn);

这一部分应该有用。