mspath
mspath

Reputation: 35

Cannot get MFC dll functions to run in .net

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);
        }
    }

Upvotes: 0

Views: 579

Answers (2)

Joseph Willcoxson
Joseph Willcoxson

Reputation: 6050

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.

Upvotes: 1

D Stanley
D Stanley

Reputation: 152624

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.

Upvotes: 1

Related Questions