Hi again,
I am able to get a pointer to a managed Brep
and use it as an ON_Brep*
in C++:
C++
int brep_get_num_verts(ON_Brep* brep)
{
// Useless test function
int N = 0;
// Iterate over the vertices just to make sure we can
for (int i = 0; i < brep->m_V.Count(); ++i)
{
ON_BrepVertex& vert = brep->m_V[i];
N++;
}
return N; // Returns the correct number of vertices
}
C#
[DllImport(Api.ApiPath, SetLastError=false, CallingConvention=CallingConvention.Cdecl)]
private static extern int brep_get_num_verts(IntPtr brep);
Brep b = ... // A valid Brep from Rhino
IntPtr ptr = Rhino.Runtime.Interop.NativeGeometryConstPointer(b);
int N = brep_get_num_verts(ptr); // success
This works fine. It also works in a similar way with Mesh
→ ON_Mesh*
, also using Rhino.Runtime.Interop.NativeGeometryConstPointer()
.
But I can’t get this to work:
C++
const char* inspect_nurbscurve(ON_Curve* curve)
{
// Useless function to test casting
std::stringstream str;
// Sanity check to make sure the type is correct. It is TL_NurbsCurve as expected.
str << curve->ClassId()->ClassName() << std::endl;
// Try to explicitly cast it to ON_NurbsCurve, but...
ON_NurbsCurve* nurbs_curve = ON_NurbsCurve::Cast(curve);
if (nullptr == nurbs_curve) // ... FAILS HERE
str << "Couldn't cast ON_Curve to ON_NurbsCurve: " << curve->ClassId()->ClassName() << " " << curve->ClassId()->ClassIdVersion() << std::endl;
else
{
// Write some data about the NurbsCurve
str << "Curve points: " << nurbs_curve->CVCount() << std::endl;
str << "Knots: " << nurbs_curve->KnotCount() << std::endl;
}
// Boilerplate stuff to return a string
const std::string tmp = str.str();
ULONG ulSize = strlen(tmp.c_str()) + sizeof(char);
char* pszReturn = NULL;
pszReturn = (char*)::CoTaskMemAlloc(ulSize);
if (pszReturn != nullptr)
strcpy_s(pszReturn, ulSize, tmp.c_str());
return pszReturn;
}
C#
[DllImport(Api.ApiPath, SetLastError = false, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStr)]
private static extern string inspect_nurbscurve(IntPtr curve);
NurbsCurve crv = ... // A valid NurbsCurve from Rhino
IntPtr ptr = Rhino.Runtime.Interop.NativeGeometryConstPointer(crv);
string res = inspect_nurbscurve(ptr); // fails
Always returns "Couldn't cast ON_Curve to ..."
It never yields a ON_NurbsCurve
correctly. I tried swapping out ON_Curve*
for ON_Object*
, ON_Geometry*
, and ON_NurbsCurve*
and cast from those, but with the same problem.
I could not find an example in the OpenNURBS docs that handles this type of situation.
I suspect it may have something to do with the pointer to the managed object being moved around, but in that case it should not work either for ON_Brep*
or ON_Mesh*
…
I have seen references to something like:
ON_Curve* curve = ...
ON_NurbsCurve nurbs_curve;
if ( 0 == curve ->GetNurbForm(nurbs_curve) )
but this always throws an access violation error for me, suggesting that either nurbs_curve
isn’t properly initialized or that something is wrong with curve
.
Is there something basic that I am missing, or a more proper way that I should be managing this? Again, no problems with ON_Brep*
or ON_Mesh*
, both of which also inherit from ON_Geometry
…
Thanks!