And I did find a workaround to have access to functions as they are specified in the rhcommon_c.dll file.
You can use the C# code fo find out what is the native methods it is calling. For example, if you navigate to the definition of the Brep.ClosestPoint method, you see this:
[ConstOperation]
public bool ClosestPoint(Point3d testPoint, out Point3d closestPoint, out ComponentIndex ci, out double s, out double t, double maximumDistance, out Vector3d normal)
{
ci = Rhino.Geometry.ComponentIndex.Unset;
s = -1.23432101234321E+308;
t = -1.23432101234321E+308;
normal = Vector3d.Unset;
closestPoint = Point3d.Unset;
return UnsafeNativeMethods.ON_Brep_GetClosestPoint(ConstPointer(), testPoint, ref closestPoint, ref ci, ref s, ref t, maximumDistance, ref normal);
}
Then, inspecting further (going to the definition of the class UnsafeNativeMethods) we can see:
[DllImport("rhcommon_c", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U1)]
internal static extern bool ON_Brep_GetClosestPoint(IntPtr pBrep, Point3d testPoint, ref Point3d closestPoint, ref ComponentIndex ci, ref double u, ref double v, double maximumDistance, ref Vector3d normal);
This basically gives the signature of a ON_Brep_GetClosestPoint function that is in the rhcommon_c.dll file. With this, I wrote something like this, which is a typedef of a function that matches the signature as we can read in the UnsafeNativeMethods C# side.
typedef BOOL(__stdcall* pON_Brep_GetClosestPoint)(
ON_Brep* pBrep,
const ON_3dPoint& testPoint,
ON_3dPoint* closestPoint,
ON_COMPONENT_INDEX* ci,
double* u,
double* v,
double maximumDistance,
ON_3dVector* normal);
Finaly, to call this function in C++, you first need to make sure that the dll is loaded (in my tests sometimes it wasn’t loaded previously by Rhino).
// This is a global variable that contains the pointer to the function in the rhcommon_c.dll
pON_Brep_GetClosestPoint ON_Brep_GetClosestPoint = nullptr;
// I call this whenever I need to be sure that I can use a rhcommon_c.dll function
// It checks if the module is loaded in the current rhino instance, otherwise it loads.
// This is still BETA - for sure there are improvements.
void LoadRhCommonC()
{
pON_Brep_GetClosestPoint oldPtr = ON_Brep_GetClosestPoint;
//if (ON_Brep_GetClosestPoint == nullptr)
//{
// Gets all loaded modules
vector<HMODULE> lphModule(1000);
DWORD lpcbNeeded = 0;
// Is the library loaded?
HANDLE hProcess = GetCurrentProcess();
// Reads the modules of the current process
BOOL gotAll = EnumProcessModules(hProcess, lphModule.data(), lphModule.size() * sizeof(HMODULE), &lpcbNeeded);
array<WCHAR, 5000> buffer;
HMODULE rhcommonModule = from(lphModule).firstOrDefault([&](HMODULE mod)
{
GetModuleFileName(mod, buffer.data(), 5000);
wstring s(buffer.data());
auto lastSlash = s.rfind('\\');
auto libNamePos = s.find(L"rhcommon_c.dll", lastSlash);
if (libNamePos == std::wstring::npos) return false;
else return true;
});
// Wasn't loaded yet - loads
if (rhcommonModule == nullptr)
{
// Gets the name of the current process
GetModuleFileName(NULL, buffer.data(), 5000);
wstring s(buffer.data());
boost::filesystem::path rhinoPath(s);
boost::filesystem::path rhcommon_cPath = rhinoPath.parent_path();
rhcommon_cPath += boost::filesystem::path("\\rhcommon_c.dll");
// Loads the module
rhcommonModule = LoadLibrary(rhcommon_cPath.c_str());
}
if (rhcommonModule == nullptr) pagmo_throw(runtime_error, "Module rhcommon_c.dll was not loaded and could not be loaded.");
auto retFPtr = GetProcAddress(rhcommonModule, "ON_Brep_GetClosestPoint");
if (rhcommonModule == nullptr) pagmo_throw(runtime_error, "Could not find function called ON_Brep_GetClosestPoint in module rhcommon_c.dll.");
ON_Brep_GetClosestPoint = (pON_Brep_GetClosestPoint)retFPtr;
int a = 0;
a++;
//}
}
Then, to call the function you can do something like this:
ON_3dPoint closestPoint;
ON_COMPONENT_INDEX ci;
double u, v;
ON_3dVector normal;
// Tests the C function
bool ret = ON_Brep_GetClosestPoint(inBrep, inPoint, &closestPoint, &ci, &u, &v, 1000, &normal);
return closestPoint;