23

I have C++ code. That code contains Windows mobile GPS enable/disable functionality. I want to call that method from C# code, that means when the user clicks on a button, C# code should call into C++ code.

This is the C++ code for enabling the GPS functionality:

#include "cppdll.h"

void Adder::add()
{
// TODO: Add your control notification handler code here
  HANDLE hDrv = CreateFile(TEXT("FNC1:"), GENERIC_READ | GENERIC_WRITE,
                0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (0 == DeviceIoControl(hDrv, IOCTL_WID_GPS_ON, NULL, 0, NULL, 0, NULL, NULL))
  {
     RETAILMSG(1, (L"IOCTL_WID_RFID_ON Failed !! \r\n")); return;
  }
     CloseHandle(hDrv);

 return (x+y);
}

And this is the header file cppdll.h:

class __declspec(dllexport) Adder
{
  public:
   Adder(){;};
  ~Adder(){;};
 void add();
};

How can I call that function using C#?

Please, can anybody help me out with this issue?

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Piraba
  • 6,974
  • 17
  • 85
  • 135

1 Answers1

36

I'll give you an example.

You should declare your C++ functions for export like so (assuming recent MSVC compiler):

extern "C"             //No name mangling
__declspec(dllexport)  //Tells the compiler to export the function
int                    //Function return type     
__cdecl                //Specifies calling convention, cdelc is default, 
                       //so this can be omitted 
test(int number){
    return number + 1;
}

And compile your C++ project as a dll library. Set your project target extension to .dll, and Configuration Type to Dynamic Library (.dll).

enter image description here

Then, in C# declare:

public static class NativeTest
{
    private const string DllFilePath = @"c:\pathto\mydllfile.dll";

    [DllImport(DllFilePath , CallingConvention = CallingConvention.Cdecl)]
    private extern static int test(int number);

    public static int Test(int number)
    {
        return test(number);
    }
}

Then you can call your C++ test function, as you would expect. Note that it may get a little tricky once you want to pass strings, arrays, pointers, etc. See for example this SO question.

Community
  • 1
  • 1
Gleno
  • 16,621
  • 12
  • 64
  • 85
  • I would still do this: #define EXPORT __declspec(dllexport) – Stefan Steiger Feb 23 '12 at 05:28
  • 1
    @Quandary sure, whatever floats your boat. I like to specify calling convention explicitly, so I need a more advanced macro to take the type parameter, and I generally try to avoid *more advanced macros*, as they are, I'm sure you know - evil. – Gleno Feb 23 '12 at 05:38
  • Thanks for reply.I have edited code.It giving error.I have changed configuration also. Please help me. `\GpsCppToDll.cpp(2) : warning C4627: '#include "GpsCppToDll.h"': skipped when looking for precompiled header use 1> Add directive to 'stdafx.h' or rebuild precompiled header 1>.\GpsCppToDll.cpp(15) : fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?` – Piraba Feb 23 '12 at 06:26
  • It looks like you have selected to use precompiled headers when you created your project, and then forgot to include it in one of your .cpp files. You could just add a #include stdafx.h (at the very top) in your GpsCppToDll .cpp file. – Gleno Feb 23 '12 at 06:34
  • Can you please look at this question http://stackoverflow.com/questions/9410197/cant-find-pinvoke-dll-bug – Piraba Feb 23 '12 at 09:48
  • @Gleno does this solution work with unmanaged C++? I found [this](http://stackoverflow.com/a/935713/839501) answer when trying to figure out how to call C++ code from C#. The link explains how to create a managed C++ wrapper around your unmanaged C++ code. Is that not needed anymore? Or is the wrapper still needed to deal with more complicated data types? – Dan Feb 20 '14 at 03:12
  • @Dan, this is a more portable solution; but both have merits. If you are familiar and comfortable with C++/CLI and your work permits you to restrict parts of your code to C++/CLI by all means use it, because it will be easier for any nontrivial amount of work. – Gleno Feb 20 '14 at 03:49
  • @Dan oh and by the way, this method is not suitable if you C++ code throws. Then you are much better off with C++/CLi to C# approach. – Gleno Feb 20 '14 at 04:01
  • @Gleno Thanks so much for the response I will take this into account when trying to accomplish my task to port unmanged C++ apps to web through C# – Dan Feb 20 '14 at 17:52