2

This is so basic it should be easy to find. In my searches all I get is more complex solutions. Converting strings, marshaling, pinning objects. How do you simply convert from a c++/CLI int^ pointer to a native int* in C++/CLI.

The body of my function is

void Open(int ^Hndl)
{
    void Unmanaged_Open(Hndl); // How do you pass the pointer to this
}

where void Unmanaged_Open(int *handle);

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
ldiablo
  • 67
  • 11
  • Didn't work, but thanks pepper_chico... i'm still searching for an answer on the net – ldiablo Feb 14 '15 at 02:07
  • hah, I'm sorry, I guess I'm messing things up with Rust xD. You should put in an int variable, and then you do &variable. Like: `int var = *Hndl; Unmanaged_Open(&var);` – oblitum Feb 14 '15 at 02:10
  • I see, de-reference the c++/CLI pointer and use the reference to the unmanaged method. It did the trick to get the compiler to stop squawking. Thank you. – ldiablo Feb 14 '15 at 02:21
  • Why are you using `int^`? Using a value-typed boxed handle is a code smell in C++/CLI. – Ben Voigt Feb 14 '15 at 03:11
  • Hi Ben, not sure i understand your question. I am writing a wrapper. The C++ API has a pointer to an int to give me back the handle. I some how need to pass this int reference from c# to C++/CLI to the C++ API. I thought the ^ is the equivalent of a pointer in c++/CLI. – ldiablo Feb 15 '15 at 03:49

1 Answers1

3

Here is how you implement an output parameter in C++/CLI, like C#'s void func(out int x). Note that there is no int^.

void Open([OutAttribute] int% retval)
{
    int result;
    if (!UnmanagedOpen(&result))
         throw gcnew Exception("Open failed!");
    retval = result;
}

Note that it is probably even better to simply return the value. Out parameters most appear in native functions when the return value is used for error checking. You can either use exceptions in .NET for error-checking, like so:

int Open()
{
    int result;
    if (!UnmanagedOpen(&result))
         throw gcnew Exception("Open failed!");
    return result;
}

or if failure is expected (untrusted input, for example), implement the TryXYZ pattern (described on MSDN):

bool TryOpen([OutAttribute] int% retval)
{
    retval = 0;
    int result;
    if (!UnmanagedOpen(&result)) return false;
    retval = result;
    return true;
}
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Is it not conventional to leave `retval` untouched in the `false` case? Of course I'd document its value as being unspecified rather than definitively unchanged, but for the purposes of avoiding what's likely an unnecessary write... – Lightness Races in Orbit Feb 14 '15 at 03:37
  • @LightnessRacesinOrbit: Nope, in the TryXYZ design pattern, the argument passed by reference definitely assigned when leaving the function. (The C++/CLI compiler wouldn't complain if you did leave the old value, but the C# compiler generates an error.) – Ben Voigt Feb 14 '15 at 03:38
  • 1
    Good lord that's horrible :( – Lightness Races in Orbit Feb 14 '15 at 04:01
  • 1
    @LightnessRacesinOrbit: Not really horrible if you know the reason. It allows detection of use of uninitialized variables across function calls. All reference parameters in C# must be definitely assigned if the function exits normally -- if the `ref` keyword is used, it's already definitely assigned when the call happens, and if the `out` keyword is used, the function is responsible for assigning it before returning. C++/CLI doesn't enforce that, but when in Rome... – Ben Voigt Feb 14 '15 at 04:02
  • Thank you for the answer Ben. It did not occur to me to create the object inside the function and assign the returned value. It was such a basic task, I was not able to find references easily. I appreciate it very much. – ldiablo Feb 15 '15 at 03:57