Incorrect marshalling in ExchangeSharp for geom extract APIs

We extract geometry from CAD model edges and faces using the A3DSimplifyCurveWithAnalytics and A3DSimplifySurfaceWithAnalytics API calls. These take an edge’s curve or a face’s surface and identify the analytic geometry represented by the curve or surface. For example, they can identify that a face’s surface is cylindrical or that an edge’s curve is circular. Once you have that you can then get the cylinder or circle data and build a geometric object in your application.

When updating a project from Exchange 2022 U1 to 2023 SP2, the ExchangeSharp generated delegate signatures changed for these 2 functions (see ExchangeSharp, Direct/API.cs). The modified signatures do not work and do not properly identify the analytic geometry. Posting this here in case it helps others who might be using these calls.

The correct (working) version of the calls is shown below. To get it working with the latest version (this is as of 2023 SP2), you’ll need to manually edit the API.cs source file and replace the delegate signatures with what’s below.

        public delegate A3DStatus PFA3DSimplifyCurveWithAnalytics(IntPtr pCurve, double dTol, uint uNbRecognizedType, IntPtr pOptRecognizedType, out IntPtr pAnalyticCurve, ref A3DEAnalyticType peAnalyticType);

        public delegate A3DStatus PFA3DSimplifySurfaceWithAnalytics(IntPtr pSrf, double dTol, uint uNbRecognizedType, IntPtr pOptRecognizedType, out IntPtr pAnalyticSurface, ref A3DEAnalyticType peAnalyticType);

The key is in the 4th argument to each function. It was changed (in a newer version of ExchangeSharp) from an IntPtr to a ref to the enum type. This is incorrect. If you look at the C headers you’ll see that the 3rd and 4th argument provide a size and a buffer for the API to return a set of type identifiers, so passing in a ref for the 4th argument won’t work.

With the signature updated to what is shown above, our code is working correctly with 2023 SP2. Note that we do not make use of the 3rd and 4th args and so just pass in 0 and IntPtr.Zero.

I suspect there could be other API calls in the C# wrapper which are also incorrect but we have not encountered them; could be APIs we’re not using. It might be worthwhile to go over all the calls and compare with the C APIs to see if any other delegates were “broken” with recent changes for similar reasons, but that is an exercise left for the reader :slight_smile:


Thanks so much for sharing this Dave! :slight_smile: I’m sure it’ll be useful to others using C# Wrapper

like CALKINS Dave reacted to your message: