Communication between C# DLLExport function and UE4 strings problem

Has anyone got any experience with attempting to pass a FString to a C# function taking a String?

Currently I am attempting the following:

UE4 code:



        typedef void(*_TestCFunction)(FString string);

	FString filePath = FPaths::Combine(*FPaths::GamePluginsDir(), TEXT("TestPlugin/"), TEXT("CTestPlugin.dll"));
	if (FPaths::FileExists(filePath))
	{
		void *DLLHandle;
		DLLHandle = FPlatformProcess::GetDllHandle(*filePath);
		if (DLLHandle != NULL)
		{
			UE_LOG(LogLevel, Warning, TEXT("dll handle created"));
			_TestCFunction DLLFuncPtr = NULL;
			FString procName = "TestCFunction";
			DLLFuncPtr = (_TestCFunction)FPlatformProcess::GetDllExport(DLLHandle, *procName);
			if (DLLFuncPtr != NULL)
			{
                                // InputString is a FString defined prior to this function, but it does exist and does have text in it.
				DLLFuncPtr(InputString);
			}
		}
	}


C# code:



        [DllExport("TestCFunction", CallingConvention = CallingConvention.StdCall)]
        static public void TestCFunction([MarshalAs(UnmanagedType.LPWStr)]String inputstring)
        {
	    // Removed internal debugging but various things do happen here. The first is printing the String out to a log file though before any other interaction with the string
            return;
        }


There are a couple things to note here for debugging/solving purposes.

In terms of passing the string to the C# function I’ve tried passing *InputString, InputString.GetCharArray(), conversions of utf8, ansi, tchar, etc. They all seem to be corrupted as inside the C# function I print what is received to a debug file and it is not printing the proper string (It never changes in size regardless of the input string and always seems to be some garbage memory). I expect I am maybe just not converting the string to the proper encoding or format but I have yet to figure out which one it should be. Alternatively if that is not the problem I would expect I am simply passing the string incorrectly in general.

For the DLLExport I’ve attempted changing the CallingConvention to Cdecl as well as not using the MarshalAs for the string but neither of those worked either.

Also worth noting is that I have attempted compiling the DLL in both 64bit and 32bit (Although with intentions of using 64bit. 32bit was just for debugging attempts.)

Any ideas, suggestions, or anything of the sort are appreciated.

yes but not c# String, instead use string, the c# string is equivalent to char* in c++ so you need just pass the FString to char* and pass to your function



       FString fstring = "hello";
       std::string stdstring(TCHAR_TO_UTF8(*fstring));
       char* pchar = stdstring.c_str();

       myDLLfunctionWithStringParameter(pchar); // easy!!!!



cheers!

Edit: anyway, try to avoid use c#, is the last hope for something hard, usually use unreal c++ is enough for everything

Thanks for the help ZkarmaKun! I got it functional using string instead of String and passing by char*.

In regards to avoiding using C# this dynamic library is not used for actual gameplay and I didn’t wish to convert the entire thing to C++ but with some small back-and-forth calls could make it fully functional which it now is. :slight_smile:

Hello everybody

I have a problem following the tutorial for linking Dlls: A new, community-hosted Unreal Engine Wiki - Announcements and Releases - Unreal Engine Forums.

I created the Release x64 bits .dll file with visual studio in the next form:

5b66f3326cea32d948f10ad11e228fdd15e049c3.jpeg

The result of that building was:

6f689e2a8b097f56ff4f8eb7bfcb5aaa4f4427a3.jpeg

where I copied the content of the path x64/Release to the path <my_UE4_Project>/Plugins/Ejemplo_dll3. The path had the next files:
-Ejemplo_dll3.dll
-Ejemplo_dll3.exp
-Ejemplo_dll3.lib
-Ejemplo_dll3.pdb

Into the Unreal’s blueprint class I wrote the next code:

And I wrote the next blueprint nodes to check the results:

But the “Return Value” is allways -3.0 because the program generate “DLLgetCircleArea = (_getCircleArea)FPlatformProcess::GetDllExport(DLLHandle, *procName) as a null value”.

Can someone help me? I do not know what I am doing wrong. Thanks

Hola herohernan mi amigo, when you build a dll from c++ you must add something more:



      #define MY_API_EXPORT __declspec(dllexport)

      float MY_API_EXPORT getCircleArea(float radius)
      {
            return 3.1416 * (radius * radius);
      }


this allow you really export the function, check this for more info: Exporting from a DLL Using __declspec(dllexport) | Microsoft Docs

POST: anyway as i say before, is c++ you almost dont need export function in c++ to c++, every windows header is allow by unreal, and i recommend use .lib for better results.

Hello ZkarmaKun

It didn’t work. I added the expression __declspec(dllexport) that you recommend me into the .dll file but the error is the same: The code return a Null value for the expresion “(getCircleArea)FPlatformProcess::GetDllExport(DLLHandle, *procName);”

regards

While I do agree with ZkarmaKun in regards to not needing to dllexport the C++ function - in terms of curiosity and getting it functioning you should try using Dependency Walker (http://www.dependencywalker.com/) to see if the function is being properly exported and if it is, what its exact name is. The name of your import in UE4 and the export of the dll must match exactly including capitalization.

mmm seems weird, when you create a new project for build a .dll you must choose win32 application and in the wizard creator also must set DLL instead Console application, its allow you the export with __declspec(dllexport) other way you are doing something wrong!

i hope this help you

Cheers!

EDIT: and Alters in right must use exactly same name

Calling a C# function directly from C++ is impossible. C# functions are written using CIL bytecode and placed inside an assembly which is a file format specific to C# and other .NET languages. Those functions can only be run using a C# runtime like .NET or Mono. While assemblies are normally given .exe or .dll file extensions, they are not the same.

As for what you’re doing now with C++. Instead of trying to manually look up the function for each call, which would slow your function down by several orders of magnitude, you should just reference your DLL’s library and headers directly.

You’ll need to find a tutorial that explains how static or dynamic linking occurs when it comes to C++.

Hello everybody

One question? I need to add the .cpp and .h files into the Unreal project; and if that question is true, where I copy them?

Regards

Edit: is normal that http://www.dependencywalker.com/ gave me the next name of the function: ?getCircleArea@@YAMM@Z?

Edit2: Sorry, I read bad the answer given by the software. This is the correct answer that is the same name of the function into de dll project and is the name that I gave to FString procName value which is used in:

FString procName = “getCircleArea”;
DLLgetCircleArea = (_getCircleArea)FPlatformProcess::GetDllExport(DLLHandle, *procName);

std::string stdstring(TCHAR_TO_UTF8(*fstring));

Its work for English, in others languages its replace symbols to ??? ?? ??