0
votes

I'm trying to create a simple MFC DLL, exports its functions and consume in a C# .net project In the code below I have two methods in the DLL, I have taken the suggestions of the posters to the original question. I'm reposting the current code, I get the error

{ "Unable to find an entry point named '_Worker_Create@0'in DLL 'C:\Users\mspath\Documents\MDS_SIMCA\DevSIMCA_Dll\TestDLL\Debug\MFClib.dll'.":"" }

I have used the dumpbin.exe to get the correct mangled names.

MFC DLL .cpp

   #include "stdafx.h"
    #include "Worker.h"

    Worker::Worker(void)
    {
    }

    Worker::~Worker(void)
    {
    }

    int Worker::GetInteger()
    {
        return 44;
    }

    int Worker::DoMath(int iOne, int iTwo)
    {
        return iOne * iTwo;
    }

MFC DLL .h

class Worker { public: Worker(void); ~Worker(void);

static int GetInteger ();
static int DoMath (int iOne, int iTwo);

};

MFCLib.cpp

extern "C"
{
    __declspec(dllexport) void * __stdcall Worker_Create()
    {
        return new Worker();
    }

    __declspec(dllexport) void  * __stdcall Worker_Destroy(Worker * instance)
    {
        delete instance;
        instance = 0;
        return instance;
    }

    __declspec(dllexport) int __stdcall Worker_DoMath(Worker * instance, int i, int j)
    {
        return instance->DoMath(i, j);
    }
}

C# .net

   public partial class MainWindow : Window
    {
/*
 *          from dumbin.exe /exports:
 *          
          1    0 00011519 _Worker_Create@0 = @ILT+1300(_Worker_Create@0)
          2    1 00011230 _Worker_Destroy@4 = @ILT+555(_Worker_Destroy@4)
          3    2 000110D2 _Worker_DoMath@12 = @ILT+205(_Worker_DoMath@12)
*/
        [DllImport("C:\\Users\\mspath\\Documents\\MDS_SIMCA\\DevSIMCA_Dll\\TestDLL\\Debug\\MFClib.dll",
                EntryPoint = "_Worker_Create@0",
                ExactSpelling = false,
                CallingConvention = CallingConvention.StdCall)]
        public extern static IntPtr Worker_Create();

        [DllImport("C:\\Users\\mspath\\Documents\\MDS_SIMCA\\DevSIMCA_Dll\\TestDLL\\Debug\\MFClib.dll",
                EntryPoint = "_Worker_Destroy@4",
                CallingConvention = CallingConvention.StdCall)]
        public extern static IntPtr Worker_Destroy(IntPtr iptr);

        [DllImport("C:\\Users\\mspath\\Documents\\MDS_SIMCA\\DevSIMCA_Dll\\TestDLL\\Debug\\MFClib.dll",
                EntryPoint = "_Worker_DoMath@12",
                CallingConvention = CallingConvention.StdCall)]
        public extern static int Worker_DoMath(IntPtr instance, int i, int j);

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            IntPtr instance = Worker_Create();

            int i = Worker_DoMath(instance, 4, 2);

            Worker_Destroy(instance);
        }
    }
2
Yes, I've tried using the extren "c", and just use simple name and still same error - mspath
GetInteger and DoMath are instance functions of the class Worker, the easiest way around this is to create a non-instance function in the DLL that creates the instance and returns the result, otherwise you have to figure out a way to create an instance of Worker and then you can run those functions on it. As it stands, they are not entry points in the DLL and can't be individually run. - Ron Beyer
you can always use clr project to connect c# with c++. - SHR
@SHR: You are probably referring to C++/CLI. /clr is the compiler command line option to compile C++/CLI, not a project type. - IInspectable

2 Answers

1
votes

You have to declare external "C-style" functions outside of C++ classes. One way it to just pipe the call to the class:

__declspec(dllexport) int DoMath (int iOne, int iTwo)
{
    Worker* worker = new Worker();
    int i = worker-> DoMath(iOne, iTwo);
    delete worker;
    return i;
}

Or convert your C++ classes to C++/CLI classes and import the library as a managed library instead of an unmanaged library.

Disclaimer: My C++ is rusty so I may be slightly off on the syntax and/or proper memory management.

1
votes

Your calling convention is wrong. __declspec(dllexport) only makes the function exported, it does not make it have the standard calling convention. I would add __stdcall or WINAPI to your function signatures so that they are using standard calling. Your one function works because it has no arguments to pass or to pop off the stack.