在 C++/CLI 中传递非托管指针

发布于 2024-07-14 03:04:32 字数 981 浏览 4 评论 0原文

我正在创建一个依赖于众多 C++ 静态库的 C++/CLI 包装器 DLL。 一些函数调用需要传入非托管指针。我如何正确地传递它们?

此外,其他函数期望“this 指针”作为 void* 传入。 传递“这个”的正确方法是什么?

这是我的类定义...

public ref class RTPClient
{
    public:
        RTPClient();
        ~RTPClient();

        bool Connect();
        void Disconnect();

    private:
        CIsmaClient* mClient;
};

这是我使用有问题的指针的用法...

RTPClient::RTPClient():
    mClient(NULL)
{
    CIsmaClient::Create(&mClient, NULL, &AllocBuffer, &GetDataPointer, this);
}

&mClient 和“this”的使用导致以下结果编译器错误... 1>.\VBLoadSimulatorDll.cpp(40) : 错误 C2664: 'CIsmaClient::Create' : 无法将参数 1 从 'cli::interior_ptr' 转换为 'CIsmaClient **' 1> 和 1> [ 1> 类型=CIsmaClient * 1> ]

1>.\VBLoadSimulatorDll.cpp(40) : 错误 C2664: 'CIsmaClient::Create' : 无法将参数 5 从 'VBLoadSimulator::RTPClient ^const ' 转换为 'VOID *'

I'm creating a C++/CLI wrapper DLL that depends on numerous C++ static libraries. Some of the function calls expect unmanaged pointers to be passed in. How do i pass them properly?

Also, other functions expect a "this pointer" to be passed in as a void*. What's the right way to pass "this"?

Here's my class definition...

public ref class RTPClient
{
    public:
        RTPClient();
        ~RTPClient();

        bool Connect();
        void Disconnect();

    private:
        CIsmaClient* mClient;
};

Here's my usage where the pointers in question are used...

RTPClient::RTPClient():
    mClient(NULL)
{
    CIsmaClient::Create(&mClient, NULL, &AllocBuffer, &GetDataPointer, this);
}

The usage of &mClient and "this" cause the following compiler errors...
1>.\VBLoadSimulatorDll.cpp(40) : error C2664: 'CIsmaClient::Create' : cannot convert parameter 1 from 'cli::interior_ptr' to 'CIsmaClient **'
1> with
1> [
1> Type=CIsmaClient *
1> ]

1>.\VBLoadSimulatorDll.cpp(40) : error C2664: 'CIsmaClient::Create' : cannot convert parameter 5 from 'VBLoadSimulator::RTPClient ^const ' to 'VOID *'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若能看破又如何 2024-07-21 03:04:32

如果您将指针传递给托管类,那么很容易将 ^ 引用转换为指针,但您必须固定托管对象,以便 GC 不会在内存中移动它(从而使指针无效)

这很简单与 pin_ptr

但是您的代码正在做两件事不起作用

RTPClient::RTPClient():
        mClient(NULL)
{
    CIsmaClient::Create(
        &mClient,          // 1
        NULL, 
        &AllocBuffer, 
        &GetDataPointer, 
        this);            //2
}

1) 您试图获取托管堆上某些内容的地址(指向 mClient 指针的指针的位置位于托管堆上。

因此它可以在内存中移动,因此,编译器供应商内部指针(其值通过 GC 操作维护)需要固定。 仅当 Create 函数在其作用域结束后不希望使用该指针时才有效(如果将其传递到其他任何地方来存储它,这将导致错误)

2)您传递的是 句柄(滑稽的帽子符号)而不是指针。 (阅读维基百科关于这些的部分,它们是一个很好的概述)这不是(也不能)被非托管代码理解。

在这种情况下,我能想到此参数的唯一原因是作为传递给后续函数回调的显式状态变量(如果我错了,请纠正我)。 在这种情况下,“this”永远不会正常工作,因为一旦 pin_ptr 超出范围,它就会在内存中移动。

考虑到这一点,这里有一个(部分)更正的实现,它清楚地表明什么可以修复,什么不能修复。

RTPClient::RTPClient():
        mClient(NULL)
{
    // make it clear you want the address of the instance variable
    pin_ptr<CIsmaClient*> pinnedClient = &this->mClient; 
    CIsmaClient::Create(
        pinnedClient,          // fixed
        NULL, 
        &AllocBuffer, 
        &GetDataPointer, 
        x /* pass something else in */);            //2
}

如果您提供有关最后一个参数用途的更多信息,我可以建议可能的解决方案

If you are passing a pointer to a managed class then it is easy to convert the ^ reference into a pointer but you must pin the managed object so that the GC doesn't move it about in memory (thus invalidating the pointer)

This is simple with pin_ptr

However your code is doing two things which won't work

RTPClient::RTPClient():
        mClient(NULL)
{
    CIsmaClient::Create(
        &mClient,          // 1
        NULL, 
        &AllocBuffer, 
        &GetDataPointer, 
        this);            //2
}

1) You are trying to take the address of something on the managed heap (the location of the pointer to the pointer mClient is on the managed heap.

As such it can move in memory, thus the compiler supplier interior pointer (whose value is maintained over GC operations). This needs to be pinned and this will only work if the Create function does not expect to use the pointer after it's scope has ended (if it passes it anywhere else to store it this will lead to bugs).

2) You are passing a handle (the funny hat symbol) rather than a pointer. (Read the wikipedia section on these they are a good overview) This is not (and cannot) be understood by the unmanaged code.

The only reason I can think of for this parameter in this context is as an explicit state variable passed to subsequent function callbacks (correct me if I'm wrong). 'this' in this context is NEVER going to work properly since this can move about in memory once the pin_ptr goes out of scope.

With that in mind here is a (partially) corrected implementation making it clear what can and can't be fixed.

RTPClient::RTPClient():
        mClient(NULL)
{
    // make it clear you want the address of the instance variable
    pin_ptr<CIsmaClient*> pinnedClient = &this->mClient; 
    CIsmaClient::Create(
        pinnedClient,          // fixed
        NULL, 
        &AllocBuffer, 
        &GetDataPointer, 
        x /* pass something else in */);            //2
}

If you supply more information on what the last parameter is used for I can suggest possible solutions

放肆 2024-07-21 03:04:32

我想您会知道这是通过 void 指针传递托管引用的最简单方法:

void SomeFunction(void* input)
{
  gcroot<ManagedClass^>* pointer = (gcroot<ManagedClass^>*)(input);
  (*pointer)->ManagedFunction();
}

void Example()
{
  ManagedClass^ handle = gcnew ManagedClass();
  gcroot<ManagedClass^>* pointer = new gcroot<ManagedClass^>(handle);
  SomeFunction((void*)pointer);
  delete pointer;
}

I think you'll that this is the simplest way of passing a managed reference via a void pointer:

void SomeFunction(void* input)
{
  gcroot<ManagedClass^>* pointer = (gcroot<ManagedClass^>*)(input);
  (*pointer)->ManagedFunction();
}

void Example()
{
  ManagedClass^ handle = gcnew ManagedClass();
  gcroot<ManagedClass^>* pointer = new gcroot<ManagedClass^>(handle);
  SomeFunction((void*)pointer);
  delete pointer;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文