mono / CppSharp

Tools and libraries to glue C/C++ APIs to high-level languages
MIT License
3.14k stars 518 forks source link

simple class without dllexport lead to ctor_0 EntryPointNotFoundException #805

Closed JiangHeWei closed 7 years ago

JiangHeWei commented 7 years ago
Brief Description

OS: Windows

Used headers

class Spi { public: virtual void Callback() = 0; };

class __declspec(dllimport) Api { public: static Spi CreateApi(); virtual void RegisterSpi(Spi pSpi) = 0; };

Used settings

options.GeneratorKind = GeneratorKind.CSharp;

Target: MSVC

Stack trace or incompilable generated code

Test.cs

SuppressUnmanagedCodeSecurity] [DllImport("Test", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, EntryPoint="??0Spi@@QEAA@XZ")] internal static extern global::System.IntPtr ctor_0(global::System.IntPtr instance);

protected Spi() { Instance = Marshal.AllocHGlobal(sizeof(global::Test.Spi.Internal)); ownsNativeInstance = true; NativeToManagedMap[Instance] = this;

        // failed,because Spi don't export,only callback interface
        __Internal.ctor_0((__Instance + __PointerAdjustment));

        SetupVTables(GetType().FullName == "Test.Spi");

}

System.EntryPointNotFoundException "??0Spi@@QEAA@XZ"

realvictorprm commented 7 years ago

I'm quite surprised that you've got an error. CppSharp hasn't failed yet for me even for really big headers there weren't any dll import failures.

However, are you sure that the dll file is correct?

ddobrev commented 7 years ago

@JiangHeWei this can be fixed but requires a little setting up on your part. So in case you have control over the C++ you wrap, it would be easiest to you to instead just add an explicit empty constructor (and destructor) to Spi.

JiangHeWei commented 7 years ago

C++ dll is third part.so spi is not exported. maybe control don't "call __Internal.ctor_0((Instance + PointerAdjustment))"?

JiangHeWei commented 7 years ago

class Spi only exist virtual method for export C++ interface

JiangHeWei commented 7 years ago

if delete "__Internal.ctor_0((Instance + PointerAdjustment))". it is ok. dll sure ok.

ddobrev commented 7 years ago

@JiangHeWei if you delete that line, your object might not be properly constructed which in turn might lead to undefined behaviour. So try the following instead:

  1. Find a *-.symbols.cpp among the generated files;
  2. Add it to a C++ project and compile it;
  3. In your configuration add the resulting library to your input i.e. Module.Libraries.Add(...);
  4. Regenerate and run.

Let me know if this helps.

JiangHeWei commented 7 years ago

in C#: public SpiImp:Spi { public override Callback(){...} }

Api api = ApiInternal.CreateApi(); api.RegisterSPi(new SpiImp());

error: System.EntryPointNotFoundException "??0Spi@@QEAA@XZ"

because in auto genegrated code call "__Internal.ctor_0((Instance + PointerAdjustment))"-> SuppressUnmanagedCodeSecurity] [DllImport("Test", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl, EntryPoint="??0Spi@@QEAA@XZ")] internal static extern global::System.IntPtr ctor_0(global::System.IntPtr instance);

ddobrev commented 7 years ago

I understand what your problem is and why you think deleting the line "fixes" it. What I am telling you is that this "fix" might cause you other problems. So please try my steps above instead.

JiangHeWei commented 7 years ago

this is callback class case. "Spi" only include virtual method. don't auto generate C# wrapper class into c++?

ddobrev commented 7 years ago

Spi is inherited by some real class, for example that SpiImpl. SpiImpl silently calls the base constructor, that is, the constructor of Spi. This is standard behaviour of C++ and all other object-oriented languages. So you'd be better off actually calling that constructor.

JiangHeWei commented 7 years ago

@ddobrev i will create new c++ project to solve this.thanks.