How to pass string to a unity plugin?

Hi,

I have a problem passing strings to dll. I wrote this simple dll in visual studio 2008 for unity :

#if _MSC_VER
#define EXPORT_API __declspec(dllexport) 
#endif

#include <string.h>
#include <iostream>
#include <string>
using namespace std;

int EXPORT_API main( string st)
{

    if(st.string::compare("hello") == 0) return 1 ;
  else return 0 ;

}

but when I want to call it through unity, I have two problems : 1. It returns 0 regardless of what string I pass into it. 2. At second call it crashes.

and this is my unity code:

using UnityEngine;
using System.Runtime.InteropServices;
class SomeScript : MonoBehaviour
{
    string st = "";

   [DllImport ("UnityTexture2")]
    public static extern int  main(string st);
   void OnGUI(){
       GUILayout.Label(st);
       if (GUILayout.Button("refresh"))
            print(main ("hello"));
   }

} 

Thanks in advance.

This is not a Unity-specific concern, but rather more general to mono and system interop. You're having trouble with marshaling between managed and unmanaged code. See the Unity docs on plugins and more precisely the linked mono documentation in that page.

You should beware of function name mangling because the interop was written assuming a C ABI. If mono can't find your function in the dll, it's not going to work. To resolve this, either wrap your C++ code in an `extern C {}` and only use standard calling conventions or ensure you get the mangled name from the dll with one of your compiler's binary tools and set the DllImport.EntryPoint. Note that mangling of names is very compiler specific. Please read this section of mono's documentation on invoking unmanaged code.

The data structure of a .net language string is a fair bit different from a C++ STL string. The way they are marshaled can be handled a number of ways, but essentially it's going to marshal as some form of char array, be it a LPCSTR or wchar* or something like that, not as an STL string (since the interop is assuming a C ABI and that didn't provide for the STL string). Please read this section of the same mono documentation on marshaling strings.

As for why you're crashing, odds are it has to do with some of the above, but I can't be sure.

Also, you don't need to include iostream or string.h if you aren't using them.

I looked through the Mono docs and the plugin docs and didn’t find a good answer for this, and wanted to give some more info. I found there are a few caveats to passing a string to a C plugin.

  • Make sure your Extern “C” is set correctly to prevent the name mangling.
  • The data type passed in is a char* on OS X.
  • You must copy this data using a function such as the MakeStringCopy below

Here is an example function in C:

char* MakeStringCopy (const char* string) {
  if (string == NULL) return NULL;
  char* res = (char*)malloc(strlen(string) + 1);
  strcpy(res, string);
  return res;
}
static char* dialogTitle;

void setDialogTitle(char* title){
	dialogTitle = MakeStringCopy(title);
}

And corresponding MonoBehavior code:

[DllImport ("libraryName")]
private static extern void setDialogTitle(string title);

void Start()
{
	setDialogTitle("test title");		
}