在C ++ / CLI中传递非托管指针 [英] Passing Unmanaged pointers in C++/CLI

查看:171
本文介绍了在C ++ / CLI中传递非托管指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个依赖于许多C ++静态库的C ++ / CLI包装程序DLL。一些函数调用期望非托管指针被传入。我如何正确传递它们?



另外,其他函数期望一个this指针 void *。



$ b

这是我的课程定义... b

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

bool Connect();
void Disconnect();

private:
CIsmaClient * mClient;
};

这里是我使用的问题的指针... / p>

  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> Type = CIsmaClient *
1>]



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

解决方案

如果你传递一个指向托管类的指针,那么很容易将^引用转换为指针,但是你必须固定托管对象,使GC不移动



这是很简单的
$ b

  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)
{
//清除你想要的实例变量的地址
pin_ptr< CIsmaClient *> pinnedClient =& this-> mClient;
CIsmaClient :: Create(
pinnedClient,// fixed
NULL,
& AllocBuffer,
& GetDataPointer,
x / * pass else else * /); // 2
}

如果您提供有关最后一个参数用于我可以建议可能的解决方案


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 *'

解决方案

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

这篇关于在C ++ / CLI中传递非托管指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆