我正在尝试从托管C ++ / CLI调用本机Windows API。其中一个论点是无效**。我们的想法是该函数将分配一个内存结构并返回一个指向调用者的void指针,该指针应在下次调用时传递回API。所以我需要为托管端的指针分配存储空间,并传递对C API的引用。我无法弄清楚如何做到这一点。
我尝试在调用者中声明void *并通过各种运算符传递引用:&,internal_ptr <>,pin_ptr <>。我对IntPtr做了同样的事情。我收到错误,说编译器无法将其转换为void **。
这是使用IntPtr和pin_ptr的一次尝试。我在第28行(声明pin_ptr的行)上得到以下编译错误:
E0144“interior_ptr<System::IntPtr>
”类型的值不能用于初始化“cli::pin_ptr<void *>
”类型的实体
#include <msclr\marshal.h>
using namespace msclr::interop;
using namespace System;
namespace CLRStorage
{
public ref class CompoundFile
{
private:
String ^ pathname;
IntPtr pRootStorage;
public:
CompoundFile CompoundFile::Create(String^ path)
{
STGOPTIONS stgOptions;
stgOptions.usVersion = 1;
stgOptions.reserved = 0;
stgOptions.ulSectorSize = 4096;
stgOptions.pwcsTemplateFile = NULL;
auto cf = gcnew CompoundFile();
cf->pathname = path;
marshal_context^ context = gcnew marshal_context();
pin_ptr<void*> ppRootStorage = &cf->pRootStorage;
StgCreateStorageEx(
context->marshal_as<WCHAR*>(path),
STGM_READWRITE & STGM_CREATE,
STGFMT_DOCFILE,
0,
&stgOptions,
NULL,
IID_IStorage,
ppRootStorage);
}
};
}
IntPtr
可以转换为void*
,但它不是同一类型。
由于参数是out-only,简单的解决方案就是使用临时的:
void* pRootStorage;
StgCreateStorageEx(
context->marshal_as<WCHAR*>(path),
STGM_READWRITE & STGM_CREATE,
STGFMT_DOCFILE,
0,
&stgOptions,
NULL,
IID_IStorage,
&pRootStorage);
cf->pRootStorage = IntPtr(pRootStorage);
实际上这也会快一点,因为不需要钉扎。
您还有一个与错误的成员函数语法有关的问题。你要
static CompoundFile^ Create(String^ path)
代替
CompoundFile CompoundFile::Create(String^ path)
别忘了
return cf;
那么,marshal_context
不是ref class
,所以这一行是错误的:
marshal_context^ context = gcnew marshal_context();
而是使用
marshal_context context;
因为它不是指针,
context.marshal_as<WCHAR*>(path)