3

I have a DLL which I need to write a wrapper for. The goal is to use it in a C# .NET application so I need to use C++/CLI (never had read about it before, so I'm new to that).

The function header in the dll is the following:

extern "C" __declspec(dllexport) BOOL __stdcall PlayM4_GetPort(LONG* nPort);

The header I've defined in my wrapper is this:

bool PlayM4Wrapper::GetPort(long^ nPort);

From what I've understood, the circunflex sign (^) means that is a pointer to the argument (nPort). So what I'm trying to write is the following code but I'm getting a conversion error Error C2664 'BOOL (LONG *)': el argumento 1 no puede convertirse de 'System::Int32 ^' a 'LONG *' .

bool PlayM4Wrapper::GetPort(long^ nPort)
{
    BOOL ret =_mLoader->m_PlayM4GetPort(nPort);
    return static_cast<BOOL>(ret);
}

Can anyone please help me with this? How should I write this wrapper function?

Thanks.

Sergi Mascaró
  • 452
  • 9
  • 13
  • I think that `^` means a reference to gc-managed object, that is boxed long in this case. So you should probably use normal local variable `::LONG lport; if(FALSE != _mLoader->m_PlayM4GetPort(&lport)) { nPort = lport; return true; } else { nPort = 0; return false; }` – user7860670 Dec 10 '18 at 14:01
  • This way it will compile, that's good. But it's now throwing a System.AccessViolationException in the DLL :( . Might this have something to do with this last error? – Sergi Mascaró Dec 10 '18 at 14:59
  • Maybe you aren't allocating `nPort` object when invoking this function? – user7860670 Dec 10 '18 at 15:00
  • 2
    https://stackoverflow.com/q/39191277/17034 – Hans Passant Dec 10 '18 at 16:05
  • Do note how changing the function signature still makes sense in this case. Getting a FALSE return value is something you should almost never just pass on. No port, whatever happens next isn't going to work. So throw an exception. – Hans Passant Dec 10 '18 at 16:15
  • Thanks so much @HansPassant for the link, it helped me get this working. Post some kind of answer based on that and I'll accept it as answered! :) – Sergi Mascaró Dec 12 '18 at 08:18

1 Answers1

2

From what I've understood, the circunflex sign (^) means that is a pointer to the argument

Not in the C++ understanding of a pointer. Yes, it is a reference to an instance of an object. But this reference is nothing you can use in C++. It's not a pointer and you cannot use it as a pointer. First, a long in .NET is not a reference type, so you don't need that. But from your method signature I guess that it is used as a hidden return value, so you need to write to it and therefor indeed need a reference. Since it's not a reference type in .NET, you will need another modifier to make it possible to pass the value back:

// equivalent C# signature:
// bool GetPort(ref long nPort) 

bool PlayM4Wrapper::GetPort(long% nPort) 
{
    LONG local = nPort;

    if(_mLoader->m_PlayM4GetPort(&local))
    {
        nPort = local;
        return true;
    }

    return false;
}

Aparently, the % is called a tracking reference.

nvoigt
  • 75,013
  • 26
  • 93
  • 142