我正在研究本机C ++应用程序,我正在尝试利用来自单独程序集的一些托管类来读取/写入最初在C#中开发的数据容器。互操作层基本上是加载数据,然后将托管数据镜像到功能相当的本机数据容器中供应用程序使用(然后显然又回来写入)。
说实话,尝试这种互操作并不是非常有趣,但它主要是在这一点上工作。尽管如此,翻译的一个步骤仍然存在,并且在调试时,托管异常(System.NullReferenceException)仅在本机C ++的行上抛出。我完全不明白为什么会发生这种情况,我希望有人能够了解正在发生的事情。我甚至没想到它会在它投掷的位置处于堆栈的管理部分......
这是我们的代码所做的精简版:
// The native data types.
class cUnmanagedInterpolator
{
virtual std::vector<std::pair<double, cUnmanagedInterpolator>& GetPoints() { return mPoints; }
std::vector<std::pair<double, cUnmanagedInterpolator> mPoints;
};
class cUnmanagedInterpolator_Const : public cUnmanagedInterpolator
{
virtual double GetValue() const { return mValue; }
double mValue
};
// The managed data types (please forgive syntax errors here; they're actually written in C# in our software, and this is just to get the point across).
class ManagedInterpolator
{
property List<KeyValuePair<double, ManagedInterpolator^>^ Points = gcnew List<KeyValuePair<double, ManagedInterpolator^>();
};
class ManagedInterpolator_Const : public ManagedInterpolator
{
property double DependentValue;
};
// The function to mirror the managed data container into a native counterpart.
void CopyManagedPoints( ManagedInterpolator^ rhManagedInterpolator, cUnmanagedInterpolator* pUnmanagedInterpolator )
{
// Go through each managed point in the interpolator and add a corresponding unmanaged one.
for each( auto point in rhManagedContainer->Points )
{
// If this is a constant interpolator, just copy the values.
if( dynamic_cast<ManagedInterpolator_Const^>( point->Value ) != nullptr )
{
// Create a new unmanaged copy of the point.
// I even tried making x and r pointers and allocating the doubles on the heap with "new" to make sure they weren't somehow ending up as CLI types, but it didn't make a difference.
double x = point->Key;
double r = dynamic_cast<ManagedInterpolator_Const^>( point->Value )->DependentValue;
std::pair<double, cUnmanagedInterpolator> newPoint( x, cUnmanagedInterpolator_Const( r ) );
// The unmanaged point data was looking weird, and this appeared to be where it was happening, so create a message with what it thinks the point is at this point.
// ***The next line is where the System.NullReferenceException is thrown.***
std::string debugMessage = MakeString( newPoint.first ) + ", " + MakeString( dynamic_cast<cUnmanagedInterpolator_Const*>( &( newPoint.second ) )->GetValue() );
// Add the copy to the unmanaged interpolator.
pUnmanagedInterpolator->GetPoints().push_back( newPoint );
// ***Trying to reference the newly created point by using pUnmanagedInterpolator->GetPoints().back() also results in an exception.
// Show the debug message to the user.
AfxMessageBox( debugMessage.c_str() );
}
// Otherwise, add a new base class interpolator.
else
{
cUnmanagedInterpolator* pNewInterp = new cUnmanagedInterpolator();
// Recurse as deep as it goes.
if( pNewInterp )
{
pUnmanagedInterpolator->GetPoints().push_back( std::make_pair( point->Key, std::move( *pNewInterp ) ) );
CopyManagedPoints( point->Value, &( pUnmanagedInterpolator->GetPoints().back().second ) );
delete pNewInterp;
pNewInterp = nullptr;
}
}
}
}
// Roughly how the function would be used.
int main()
{
ManagedInterpolator^ rhManagedInterpolator = gcnew ManagedInterpolator( /*initialization information*/ );
cUnmanagedInterpolator* pNewInterp = new cUnmanagedInterpolator();
CopyManagedPoints( rhManagedInterpolator, pNewInterp );
// Use the data...
return 0;
}
内部if语句中发生异常(前面有三个星号(“***”)的注释标记出现问题的位置)。
如果代码不够清晰,请快速摘要代码:
基本上,数据容器是一个“插值器”,它包含独立和相关值对(“点”)。从属值可以是另一个插值器或标量值。作为插值器的相关值可以根据需要进行深度递归,但必须以固定值结束,该值是从插值器派生的类。
答案 0 :(得分:1)
您正在使用句柄(^
),因此这不是本机代码。问题是您的对newPoint
有cUnmanagedInterpolator
个对象作为其第二个值,您尝试dynamic_cast
到生成{{1}的行上的cUnmanagedInterpolator_Const
}。此强制转换将失败并返回NullReferenceException
,当取消引用时将导致异常。
从根本上说,当您使用nullptr
时,当您创建该对时,它会切片到cUnmanagedInterpolator_Const
,并将其身份标记为cUnmanagedInterpolator
并且成为cUnmanagedInterpolator_Const
。