我使用 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 个变体都编译时没有错误,没有例外......但是用一些垃圾值填充它的 (void *) 值,如 5,12331E-305。在非托管代码中一切正常。
这种 void* 到 C++/CLI 基本类型绑定可能会出现什么错误?