I used the code that you posted with the latest version of the library and it works great for me. One thing you can consider is wrapping like a C ++ / CLI instead of using P / Invoke, but this is another topic.
I work under the assumption that you are using Visual Studio 2010 (well, good to start somewhere :-)).
One thing that is clearly out of order:
Native:
extern "C" __ declspec (dllexport) void __stdcall convertGeocentricToMGRS (const double x, const double y, const double z, char * & mgrsString, Precision :: Enum & precision)
and C #:
[DllImport ("CoordinateConversionWrapper.dll")] private static extern void convertGeocentricToMGRS (double x, double y, double z, ref char [] mgrsString, precision accuracy);
make:
extern "C"__declspec(dllexport) void __stdcall convertGeocentricToMGRS(const double x, const double y, const double z, char** mgrsString, Precision::Enum& precision) { MSP::CCS::CoordinateSystemParameters geocentricParameters(MSP::CCS::CoordinateType::geocentric); MSP::CCS::CoordinateSystemParameters mgrsParameters(MSP::CCS::CoordinateType::militaryGridReferenceSystem); MSP::CCS::CoordinateConversionService ccs( "WGE", &geocentricParameters, "WGE", &mgrsParameters ); MSP::CCS::Accuracy sourceAccuracy; MSP::CCS::Accuracy targetAccuracy; MSP::CCS::CartesianCoordinates sourceCoordinates(MSP::CCS::CoordinateType::geocentric, x, y, z); MSP::CCS::MGRSorUSNGCoordinates targetCoordinates; ccs.convertSourceToTarget( &sourceCoordinates, &sourceAccuracy, targetCoordinates, targetAccuracy ); int nMGRSLen = strlen( targetCoordinates.MGRSString() ); ::CoTaskMemFree(*mgrsString); *mgrsString = (char *)::CoTaskMemAlloc(nMGRSLen + 1); strcpy( *mgrsString, targetCoordinates.MGRSString() ); precision = targetCoordinates.precision(); }
Note that char is passed as a pointer to a pointer and used by CoTaskMemFree / CoTaskMemAlloc / strcpy (including Objbase.h for CoTaskMemAlloc)
And in C # code you can:
[DllImport("MSPGeotransTest.dll", CharSet= CharSet.Ansi))] public static extern void convertGeocentricToMGRS(double x, double y, double z, ref string mgrsString, ref PrecisionEnum precision);
Where:
public enum PrecisionEnum : uint { degree = 0, tenMinute = 1, minute = 2, tenSecond = 3, second = 4, tenthOfSecond = 5, hundrethOfSecond = 6, thousandthOfSecond = 7, tenThousandthOfSecond = 8 }
Perhaps there are other possibilities for this ...
Some other useful things:
To be able to debug, make sure that:
In the menu "Tools"> "Options"> "Debug"> "General", "Enable only my code" is not installed.
In the project> Properties> Debug tab, the option "Enable unmanaged code debugging" is checked.
Put a breakpoint in the C # method and when the breakpoint is reached, you can go to F11 and get the C ++ code ...
I compiled C ++ Dll by selecting "Use multibyte character set" (Configuration Properties \ General \ Character Set)
It would also seem that the CoordinateConversionService constructor throws a CoordinateConversionException if it cannot load the configuration files (it searches for them, it will appear in a path that can be configured through an environment variable named MSPCCS_DATA and if the environment variable is not defined it looks for them in. ./../data/ regarding exe path).
Perhaps in C ++ wrapper methods you can catch any exceptions that may be caused by called methods and return an error code ... Ie other situations that cause exceptions are associated with incorrect input coordinates, etc.
As I said, I have a working example, so if you want, I can send it to you ...