我使用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 用一些垃圾值填充其(void *)值,如5,12331E-305。在非托管代码中,一切正常。
对于C ++ / CLI基本类型绑定,这样的void *会出现什么错误?
答案 0 :(得分:0)
问题在于内部数据是由此库中的浮点数呈现的。因此,当它在C#侧被映射并处理为双精度时,它给出了5,12331E-305。
这3个变量中的每一个都有效。并且,从我的角度来看,使用 pin_ptr pinnedEventX =&amp; mEventX; 在这种情况下是不正确的,因为它不会在函数执行之间持续存在;
我不确定,为什么这种“浮动”情况是在原生C ++中处理的。正如我之前写的那样,没有任何问题。