11

I need help setting up a simple C++/C# SWIG project. I am having a hard time putting together a C++ project that uses the SWIG bindings. I'm using Visual Studio 2010 and the most recent version of SWIG.

My code is simply:

cpp_file.h:

#pragma once
class cpp_file
{
public:
    cpp_file(void);
    ~cpp_file(void);

    int times2(int arg);
};

cpp_file.cpp

#include "cpp_file.h"
cpp_file::cpp_file(void)
{
}
cpp_file::~cpp_file(void)
{
}
int cpp_file::times2(int arg)
{
return arg * 2;
}

And my SWIG interface file is:

cpp_file.i

/* cpp_file.i */
%module cpp_file
%{
/* Put header files here or function declarations like below */
extern int times2(int arg);
%}
extern int times2(int arg);

I can compile this project fine. I then run the SWIG command to generate the wrapper:

swig -csharp "C:/pathToFile/cpp_file.i"

I don't know what to do at this point. I can't find any tutorials or documentation that explains what to do in Visual Studio 2010.

When I add the *cpp_file_wrap.c* file that SWIG generates to my Visual Studio 2010 project and attempt to build the project, I get two linker errors.

  1. error LNK1120: 1 unresolved externals
  2. error LNK2001: unresolved external symbol _times2

The first error message points to my dll file. The second error points to some object file (*.obj). The symbol that the error message mentions "_times2" is no where to be found in my project.

How can I move forward with my simple project? Is there some tutorial or some documentation that explains this process step-by-step? I can't find anything that involves C++ with SWIG, C#, Visual Studio 2010, and .Net v4.0.

user1214135
  • 625
  • 2
  • 11
  • 22

2 Answers2

21

Step-by-Step instructions to completely build in the VS2010 IDE:

  1. Create a solution with two projects:
    • C# Console Application
    • C++ Win32 Console Application (Name=cpp, DLL, empty project). If you choose a different name, don't use the name of a class in your project and update the .i file %module name to match.
  2. Create a folder in the C# project called Generated.
  3. Add your .cpp, .h, and .i file to the DLL with the modifications below.
    • Note the whole class has to be exported. Replace <project> with the name of the project. There will be a preprocessor definition <project>_EXPORTS already defined for your DLL project (see Project, Properties, C++, Preprocessor).
    • The module name cannot match a class name in the module.
    • %include <windows.i> helps SWIG understand certain "Window-isms" like __declspec.

cpp_file.h

#pragma once

#ifdef <project>_EXPORTS
#define <project>_API __declspec(dllexport)
#else
#define <project>_API __declspec(dllimport)
#endif

class <project>_API cpp_file
{
public:
    cpp_file(void);
    ~cpp_file(void);

    int times2(int arg);
};

cpp_file.i

%module cpp

%{
#include "cpp_file.h"
%}

%include <windows.i>
%include "cpp_file.h"
  1. Select cpp_file.i, Properties, General, Item Type as Custom Build Tool.
  2. Select Apply to create the Custom Build Tool property group.
  3. In Custom Build Tool, General, Command Line enter:
    swig -csharp -c++ -outdir GeneratedFolderPath cpp_file.i
  4. In Outputs, enter cpp_file_wrap.cxx, and click OK to close the dialog.
  5. Right-click cpp_file.i and Compile. This should create four files: three in the C# Generated folder and one in the C++ project.
  6. Create a Generated Files filter in the C++ project and add cpp_file_wrap.cxx to it.
  7. Add the three Generated files to the C# project's Generated folder.
  8. Right-click the C# project and add the C++ project as a dependency.
  9. In the C# project's Properties, Build tab, change the Output Path from bin\Debug to ..\Debug or whatever the relative path to the C++ Project output directory is. The .exe and .dll need to be in the same directory.
  10. In the C# project's Main, add the lines:
    var cpp = new cpp_file();
    Console.WriteLine(cpp.times2(5));
  11. Build the solution.
  12. Run the C# project.

Good luck! Let me know if you get it to work. I can expand on anything unclear.

Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • It worked! Thank you Mark. I had a little trouble making sure my output directory was correct (step #9). I got an error saying that my DLL couldn't be loaded. When I fixed my output directory, it worked. Also, in the first step #3, in the third bullet point, I think you meant to type "%include helps SWIG". The cpp_file.i has so it's not really a problem. Thanks again. – user1214135 Mar 22 '12 at 12:19
0

I've only used SWIG a small amount but it looks like you're trying to export a function named times() in your .i file which doesn't exist. You do have a cpp_file::times() method but that is not exported. You either need to define the times() function or export the entire cpp_file class via SWIG.

I would spend some time reading the official SWIG documentation, particularly the SWIG and C++ section. There is also this question on SO which has some information related to SWIG and VS2010.

Community
  • 1
  • 1
uesp
  • 6,194
  • 20
  • 15