5

I am using SWIG to generate a DLL that will expose C++ functionality to a C# project. At the moment I:

  1. Define a SWIG interface file

    %module example
    %{
    /* Includes the header in the wrapper code */
    #include "../pointmatcher/PointMatcher.h"
    %}
    
    ...
    
    %include "../pointmatcher/PointMatcher.h"
    
  2. Use SWIG to generate a .cxx wrapper

    swig.exe -c++ -csharp -outdir csharp example.i
    
  3. Compile the .cxx wrapper with MSBUILD via CMake

    # create wrapper DLL
    add_library(example SHARED ${WRAP_CSHARP_FILE})
    target_link_libraries(example pointmatcher)
    install(TARGETS example
            ARCHIVE DESTINATION ${INSTALL_LIB_DIR}
            LIBRARY DESTINATION ${INSTALL_LIB_DIR}
            RUNTIME DESTINATION ${INSTALL_BIN_DIR})
    

I then have a DLL file (example.dll) which I can inspect via Dependency Walker, and confirm that methods are being exposed as follows:

Dependency Walker inspection of DLL

However, when I try to add this MSVC DLL as a reference to a C# project I get the error "It is not a valid assembly or COM component".

Based on answers at How can I add a VC++ DLL as a reference in my C# Visual Studio project? I have confirmed that SWIG itself generates P/Invoke calls, and that tlbimp doesn't recognise the DLL either.

Community
  • 1
  • 1
lofidevops
  • 15,528
  • 14
  • 79
  • 119
  • [Swig should also create .cs files for you to add to your project if you pass it -csharp](http://www.technical-recipes.com/2013/getting-started-with-swig-interfacing-between-c-and-c-visual-studio-projects/) – Mark Jansen Aug 04 '15 at 11:07
  • 1
    @MarkJansen yes, but I can't add the C++ DLL to the C# project – lofidevops Aug 04 '15 at 11:30
  • may need to invoke /MT instead of /MD when compiling (not 100% sure if this is the cause of my problem, but apparently I need it anyway) – lofidevops Aug 04 '15 at 11:52

1 Answers1

3

You don't add the C++ dll to your project in the same way you would a C# dll. Instead it is called through the PInvoke system.

SWIG will generate some C# code for you, the easiest way to access the dll is to include those files in your porject, which expose the dll functionality through some C# functions which you can call.

You can also use the dll through PInvoke yourself. You need to create a C# function that will act as a wrapper:

C++ Header:

#ifndef TESTLIB_H
#define TESTLIB_H

extern "C" {
    int myfunc(int a);
}

#endif

C++ Code:

int myfunc(int a)
{
    return a+1;
}

C# Code:

using System;
using System.Runtime.InteropServices;

class Libtest
{
    [DllImport ("function")]
    private static extern int myfunc(int a);

    public static void Main()
    {
        int val = 1;
        Console.WriteLine(myfunc(val));
    }
}

Output:

2

Location of the DLL

The compiled C++ dll needs to either be copied into the C# project bin directory, or if the path is known it can be added to the DllImport call:

[DllImport("path/to/dll/function.dll")]

To achieve this with swig use the -dllimport flag:

swig -cpp -csharp ... -dllimport "/path/to/dll/function.dll" ...

If you want to set the path dynamically (to allow for loading 32-bit or 64-bit versions dynamically selected at runtime) you can use the kernel32 function SetDllDirectory which is also loaded using DllImport.

Tim B
  • 3,033
  • 1
  • 23
  • 28
  • So I need to add a C# project to the solution that contains the C++ project? And the C# project must depend on the C++ project, rather than having a Reference to a DLL? – lofidevops Aug 04 '15 at 13:03
  • @d3vid The projects don't need to be within the same solution but (assuming visual studio will let you do this) they could be. You just need the location of the generated dll, or to copy the dll into the bin folder of the C# project. – Tim B Aug 04 '15 at 13:09
  • thanks! my problem was not knowing that the C++ DLL was included by location rather than as a Reference - it is now cooperating :) – lofidevops Aug 04 '15 at 13:38
  • @d3vid Ahha, yes, I think that often trips people up. Glad it's sorted now! – Tim B Aug 04 '15 at 13:41