Unity can not load native plugin when source c++ code contains "new"

I am not sure if it is a bug or not, maybe I am doing something completely wrong.
Following basically the same steps as in this article from unity learn I got a simple plugin written in c++
to be correctly imported and executed from a unity project.

The C# side contains the following code:

public class NativePluginWrapper {
    [DllImport("SomePlugin", CallingConvention = CallingConvention.Cdecl)]
    public static extern int getSomeNumber();
}
...
// in some Start()
var result = NativePluginWrapper.getSomeNumber();
Debug.Log(result)

Where SomePlugin refers to a dll named SomePlugin.dll placed in Assets/Plugins which is compiled
from the following c++ code:

#include "NativePlugin.h"

extern "C" {
    DllExport int getSomeNumber() {
        return 1234;
    }
}
#pragma once

#define DllExport __declspec (dllexport)

extern "C" {
    DllExport int getSomeNumber();
}

This setup works and the log shows the correct number returned by the plugin.

Now, adding any kind of “new” expression inside of the c++ code, for example just
int* x = new int[1];
leads to the following exception:

DllNotFoundException: NativePlugin assembly:<unknown assembly> type:<unknown type> member:(null)

What is happening here? Is allocating memory not supported / not allowed or am I doing something fundamentally wrong?

I’ve not had problems with new and native dll’s. so I can confirm they work. also typo in NativePlugin.h “void” instead of “int” getSomeNumber();

also another great resource is GitHub - Unity-Technologies/NativeRenderingPlugin: C++ Rendering Plugin example for Unity if going deeper with functionality of your plugin. (but anything with device context stuff, has to only be done on the rendering thread - so cannot call functions that use device context from c# directly) that tripped me up when I was learning to make unity plugin. just thought I’d mention that if ever needed.

1 Like

I use malloc/free all over the place… are you able to hit those instead?

Is it your calling convention? Did you try stdcall? I’ve never bothered specifying calling convention in my interops for any of the Unity targets. But then again I’ve never called new in my native C / C++ either… all my stuff is C. :slight_smile:

1 Like

Thank you for the resources. To your first point, I just made a copy paste error in my initial post, I corrected it.
I have found an other example of working / non working pair:

working:

extern "C" {
    int getSomeNumber() {
        auto *vec = new std::vector<int>();
        vec->push_back(20200);
        return (*vec)[0];
    }
}

Changing the return type to int* and returning &(*vec)[0] instead makes the dll fail to load.

I read about the calling convention in some stack overflow post and just tried it out, but the default produces the same error.

I would really like to find a way to debug the runtime itself to check what exactly is causing the dll load to fail…

no prob, thought so but thought Id mention it). if return type is int* getSomeNumber() then I think you would need unsafe on the c# side. If I have time today will have look and see if I can replicate.

side note: one strange thing I noticed with the project I linked to above was I could only use extern c in one .h file. as it would only export symbols for function in that .h file. might be a unity specific thing with that rendering project thought I would mention that too.

Are you able to return the memory pointer (address of this array) directly?

Obviously your interop would need to return System.IntPtr instead of int and marshal it into something useful.

When I return a good old null-terminated C string, I used this C# interop:

private static extern System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1);

and the native C looks like:

char            *dispatcher1_entrypoint1( int opcode1, int arg1);

and C# stands the string up as:

return Marshal.PtrToStringAnsi( dispatcher1_entrypoint1( (int)opcode, arg1));

Here was my setup for pinning a pixel array for native code fill it out:

Pinning a texture for manipulation via native code:

This is all for my KurtMaster2D collection of MS-DOS and PalmOS games I wrote back in the day:

Apple iTunes: ‎KurtMaster2D on the App Store
Google Play (including TV): https://play.google.com/store/apps/details?id=com.plbm.plbm1