将 void * 指针绑定到基本类型的 C++/Cli 指针

发布于 2024-11-08 06:02:53 字数 1942 浏览 0 评论 0原文

我使用 C++ cli 对一些科学库 (http://root.cern.ch) 从非托管世界到托管世界做了一些薄包装。

特殊文件格式的读取(这是主要目标)是通过以下方式实现的:
1) 一次生命周期调用 SetBranchAddress(const char name, void* outputVariable) 让它知道变量的地址
2)比你N次调用GetEntry(ulong numberOfRow),它用适当的值填充这个void*outputVariable

我给出了这个用法示例:

double myValue; //this field will be filled

//We bind myValue to the 'column' called "x" stored in the file"
TTree->SetBranchAddress("x", &myValue); 

// read first "entry" (or "row") of the file
TTree->GetEntry(0); 

// from that moment myValue is filled with value of column "x" of the first row
cout<<"First entry x = "<<myValue<<endl; 

TTree->GetEntry(100); //So myValue is filled with "x" of 101 row
...

因此,在 C++/CLI 代码中,问题在于将托管基本类型绑定到此 void * 指针;

我尝试了 3 种方法:

namespace CppLogicLibrary {
public ref class SharpToRoot
{        
       double mEventX;
       double *mEventY;
       IntPtr memEventZ;

       ///Constructor
       SharpToRoot()
       {
          mEventy = new double();
          memEventZ= Marshal::AllocHGlobal(sizeof(double));
       }

       void SetBranchAddresses()
       {
           pin_ptr<double> pinnedEventX = &mEventX;
           mTree->SetBranchAddress("ev_x", pinnedEventX);
           mTree->SetBranchAddress("ev_y", mEventY);
           mTree->SetBranchAddress("ev_z", memEventZ.ToPointer());
           ...
           //now I read some entry to test... just in place
           mTree->GetEntry(100);
           mTree->GetEntry(101);
           double x = mEventX;
           double y = *mEventY
           double z = (double)Marshal::PtrToStructure(memEventZ, Double::typeid);
       }

       ...

所有 3 个变体都编译时没有错误,没有例外... BUT 用一些垃圾值(如 5,12331E-305)填充其 (void *) 值。在非托管代码中一切正常。

这种 void* 到 C++/CLI 基本类型的绑定可能会出现什么错误?

I do some thin wrapper of some scientific library (http://root.cern.ch) from unmanaged to managed world using C++ cli.

Reading of the special file format (which is the main goal) is implemented through:
1) Once a lifetime call of SetBranchAddress(const char name, void* outputVariable) to let it know an address of your variable
2) Than you N time call GetEntry(ulong numberOfRow) wthich fills this void* outputVariable with the appropriate value;

I put this example of usage :

double myValue; //this field will be filled

//We bind myValue to the 'column' called "x" stored in the file"
TTree->SetBranchAddress("x", &myValue); 

// read first "entry" (or "row") of the file
TTree->GetEntry(0); 

// from that moment myValue is filled with value of column "x" of the first row
cout<<"First entry x = "<<myValue<<endl; 

TTree->GetEntry(100); //So myValue is filled with "x" of 101 row
...

So in C++/CLI code the problem is with binding managed elementary types to this void * pointer;

I have tried 3 approaches:

namespace CppLogicLibrary {
public ref class SharpToRoot
{        
       double mEventX;
       double *mEventY;
       IntPtr memEventZ;

       ///Constructor
       SharpToRoot()
       {
          mEventy = new double();
          memEventZ= Marshal::AllocHGlobal(sizeof(double));
       }

       void SetBranchAddresses()
       {
           pin_ptr<double> pinnedEventX = &mEventX;
           mTree->SetBranchAddress("ev_x", pinnedEventX);
           mTree->SetBranchAddress("ev_y", mEventY);
           mTree->SetBranchAddress("ev_z", memEventZ.ToPointer());
           ...
           //now I read some entry to test... just in place
           mTree->GetEntry(100);
           mTree->GetEntry(101);
           double x = mEventX;
           double y = *mEventY
           double z = (double)Marshal::PtrToStructure(memEventZ, Double::typeid);
       }

       ...

All of 3 variants are compiled with no errors, goes with no exceptions... BUT fills its (void *) values with some rubbish value like 5,12331E-305. In unmanaged code all works fine.

What could be the error with such void* to C++/CLI elementary types binding?

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

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

发布评论

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

评论(1

放低过去 2024-11-15 06:02:53

问题是内部数据是由该库内的浮点数表示的。因此,当它在 C# 端作为双精度数进行映射和处理时,它给出 5,12331E-305。

这 3 种变体均有效。而且,从我的角度来看,使用
pin_ptr pinnedEventX = &mEventX;
在这种情况下是不正确的,因为它在函数执行之间不会持续;

我不确定为什么这种“浮动”情况是在本机 C++ 中处理的。正如我之前写的,没有任何问题。

The problem was that internally data was presented by floats inside of this library. So, when it was mapped and processed as doubles on the C# side, it gave 5,12331E-305.

Each of this 3 variats worked. And, from my point of view, using of
pin_ptr pinnedEventX = &mEventX;
was improper in this case, because it doesn't persist between functions execution;

What I'm not sure, why this "float" situation was handled in native C++. As I wrote before, there wasn't any problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文