C++/CLI 指针问题 = 有趣!
我一直在将一堆旧的 C++ 代码转换为 C++/CLI 代码,我想我已经把自己编码到了一个角落。
我的目标是采用非托管 C++ 库和一堆头文件,并将其功能公开给 C# 解决方案。从互联网上阅读,执行此操作的标准方法是:
- 创建两个 C++ 类:一个托管,另一个非托管。
- 非托管类将整理 C++ 库中的对象以提供所需的功能。
- 托管类将包装非托管类中的所有公共方法。每个包装器方法都会处理从 String^ 到字符串等的必要转换。
但是,我的场景并不是很复杂,所以我决定尝试在一个类中实现所有内容。我现在正在努力解决一个生成 AccessViolationExceptions 的特殊问题。
我的头文件如下所示:
public ref class ManagedClass
{
public:
ManagedClass();
void CreateUnmanagedObject(String^ param1);
void UseUnmanagedObject();
UnmanagedObject *myUnmanagedObject;
}
我的 cpp 文件如下所示:
void ManagedClass::CreateUnmanagedObject(String^ param1)
{
/* Convert params, use them in some way. */
/* capture the output of this library call to the pointer defined in ManagedClass.*/
myUnmanagedObject= &(LibrayObject.LibraryMethod1());
}
void ManagedClass::UseUnManagedObject()
{
/* This function will pass the Unmanaged object into
* a library function which will do some work on it.
*/
LibraryObject.LibraryMethod2(*myUnmanagedObject);
/* Whoops! System.AccessViolationException is thrown! */
}
有趣的是,如果我在 LibraryMethod1 之后立即在 CreateUnmanagementObject 中调用 LibraryMethod2,则它可以正常工作。但是CreateUnmanagementObject退出后,好像myUnmanagementObject指向的内存就丢失了。
任何人都可以看到发生这种情况的原因吗?
编辑:库声明如下所示:
UnmanagedObject LibraryMethod1();
void LibraryMethod2(UnmanagedObject ¶m);
I've been converting a bunch of old C++ code into C++/CLI code, and I think I've coded myself into a corner.
My goal was to take an unmanaged c++ library and a bunch of header files and expose their functionality to a C# solution. From reading on the internet, the standard way to do this is to:
- Create two c++ classes: one managed, the other unmanaged.
- The unmanaged class will wrangle the objects in the c++ library to provide the desired functionality.
- The managed class will wrap all of the public methods in the unmanaged class. Each wrapper method would handle the necessary conversions from String^ to string, etc..
But, my scenario isn't very complex, so I decided to just try and implement everything in one class. I am now wrestling with a peculiar problem that generates AccessViolationExceptions.
My header file looks like this:
public ref class ManagedClass
{
public:
ManagedClass();
void CreateUnmanagedObject(String^ param1);
void UseUnmanagedObject();
UnmanagedObject *myUnmanagedObject;
}
And my cpp file looks like this:
void ManagedClass::CreateUnmanagedObject(String^ param1)
{
/* Convert params, use them in some way. */
/* capture the output of this library call to the pointer defined in ManagedClass.*/
myUnmanagedObject= &(LibrayObject.LibraryMethod1());
}
void ManagedClass::UseUnManagedObject()
{
/* This function will pass the Unmanaged object into
* a library function which will do some work on it.
*/
LibraryObject.LibraryMethod2(*myUnmanagedObject);
/* Whoops! System.AccessViolationException is thrown! */
}
The intriguing thing is that if I call LibraryMethod2 within CreateUnmanagedObject immediately after LibraryMethod1, it works fine. But after CreateUnmanagedObject exits, it seems that the memory pointed to by myUnmanagedObject is lost.
Can anyone see a reason that this is happening?
Edit: Library declarations look like this:
UnmanagedObject LibraryMethod1();
void LibraryMethod2(UnmanagedObject ¶m);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
你没有获取临时变量的地址吗?如果
返回某个值的副本,那么您正在获取局部变量的地址,该地址在方法末尾超出了范围。之后使用该地址是未定义的行为,在这种情况下会导致访问冲突!
Are you not taking the address of a temporary variable? If
returns a copy of some value, then you are taking the address of a local variable, which goes out of scope at the end of the method. Using that address afterwards is undefined behavior, in this case causing access violations!
不确定你真正的问题是什么,但看起来完全错误。托管包装器应该是与非托管包装器非常接近的传真。让我们从这样的非托管声明开始工作:
那么您的包装器应该类似于这样:
这里的秘诀是非托管类的实例是包装器中的指针。只需将托管方法调用委托给非托管方法即可。是的,一些带有字符串的骗局,如图所示。并确保当用户或垃圾收集器处理该本机实例时将其删除。
Not sure what your real problem might be but it looks all wrong. The managed wrapper should be a pretty close facsimile to the unmanaged one. Let's work from an unmanaged declaration like this:
Then your wrapper ought to resemble this:
The recipe here is that the instance of the unmanaged class is a pointer in the wrapper. And just delegate the managed method calls to the unmanaged one. Yes, some hokeypokey with strings, as shown. And making sure that this native instance gets deleted when either the user or the garbage collector gets around to it.
您正在获取指向堆栈临时变量的指针。纯属运气好,如果你一个接一个地调用这些方法,它就指向了一些东西。
在熟悉 C# 多年之后,我正在用 C++ 编写一些代码,并且必须告诉您,我时不时也会遇到同样的问题。
简而言之 - 不要获取临时创建的地址并将其存储在指针中以供以后使用。时期。
You are taking a pointer to the on-stack-temp variable. By pure luck, it points to something if you call the methods one after another.
I am coding something in c++ after many years of c# comfort, and must tell you that now and then I have same issues.
In short - don't take an address of something that is created temporary and store it in a pointer for later use. Period.