mono / CppSharp

Tools and libraries to glue C/C++ APIs to high-level languages
MIT License
3.03k stars 497 forks source link

STL not exported or Crashes #684

Open greg002 opened 7 years ago

greg002 commented 7 years ago
Brief Description

In the documentation, i can read that STL is supported. I try to wrap a class using std::string and std::vector.

1) If i use std::string, the function which use std::string is not exported (getStdString() in this example), it's ignored:

class __declspec(dllexport) MyClass
{
private:
    std::string             _str;
public:
    std::string getStdString(){ return _str; };
};

2) If i use std::vector, the cppSharp wrapper generator crash:

class __declspec(dllexport) MyClass
{
private:
    std::vector<int>        _vectorInt;
public:
    std::vector<int> getVectorInt(){ return _vectorInt; };
};

3) If i put the std::vector variable as public (without function access). The warpper generate the .cs wrapper. But it crash when i try to compile my test program:

Erreur 14 Le type 'int' ne peut pas être utilisé comme paramètre de type 'T' dans le type ou la méthode générique 'Std.Vector'. Il n'y a pas de conversion boxing de 'int' en 'CppSharp.Runtime.ICppMarshal'. C:...\Wrapper.cs 154 32 UtilisationCSharp

OS: Windows / OS X / Linux (include version and/or distro)

Windows 7

Used headers
Used settings
using CppSharp.AST;
using CppSharp.Passes;
using System;

namespace CppSharp
{
    class Wrapper : ILibrary
    {
        public void Setup(Driver driver)
        {
            var options = driver.Options;
            options.LibraryName = "myTest";
            options.Headers.Add("Test.h");
            options.addIncludeDirs("C:/myTest/myTest/");
            options.OutputDir = "TestGreg";
            options.Libraries.Add("C:/myTest/myTest.lib");
        }

        public void SetupPasses(Driver driver)
        {
        }

        public void Preprocess(Driver driver, ASTContext ctx)
        {
        }

        public void Postprocess(Driver driver, ASTContext ctx)
        {
        }

        static class Program
        {
            public static void Main(string[] args)
            {
                Wrapper wrap = new Wrapper();
                ConsoleDriver.Run(wrap);
                Console.ReadKey();
            }
        }
    }
}

Target: MSVC/GCC/Clang

Visual Studio 2013

Other settings

Stack trace or incompilable generated code
ddobrev commented 7 years ago

The support for STL is still in progress which we have indicated. std::vector in particular is not supported yet. std::string is supported but you used an old version. We have some bugs to fix but we hope to release a new one later today.

greg002 commented 7 years ago

Thanks. What is the best way to use CppSharp with a C++ library which has never been written to be used by a C# ? Do i have to create a C++ interface with basic types (variables and functions) ? How does QTSharp solves this problem ?

tritao commented 7 years ago

If you are writing a C++ library from scratch, then sticking to basic types as you said is the way to go. Use simple C++ classes with single inheritance, and do not use templates and standard library types on the public interfaces and you should have a very easy time to bind it to C#.

We'll be continuing the work to further support C++ standard library types but as they rely heavily on templates it's hard to do it and will always add more complexity to the bindings since native code also needs to be generated alongside the managed code.

@ddobrev solved the problem for QtSharp by spending thousands of hours fixing bugs in CppSharp so it can deal with the entire Qt codebase. And Qt uses their own container types that are the same on every platform and easier to support than the C++ ones which details vary per compiler.

greg002 commented 7 years ago

Thanks. The library i have to wrap use QT (Core: QString, QMap, QVector, QSet, ... and QdateTime). QTSharp is written to use QT with C#, not to wrap a user c++ library which use QT. But would it be easy to use some part of the code of QTSharp to wrap a c++ library which use QT Core ?

tritao commented 7 years ago

You can try to re-use QtSharp type maps in your project, https://github.com/ddobrev/QtSharp/blob/master/QtSharp/QString.cs.

mwallnoefer commented 7 years ago

I have done some test with a header including #include <string> (platform is Windows with Visual Studio 2013).

This is the outcome:

Parsing code...
Unhandled declaration kind: ClassScopeFunctionSpecialization
   (line 1)
Parsed 'lib\qttestlib.h'
Processing code...

Unhandled Exception: System.InvalidOperationException: Sequence contains more than one matching element
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source, Func`2 predicate)
   at CppSharp.Passes.IgnoreSystemDeclarationsPass.VisitClassDecl(Class class)
   at CppSharp.AST.Class.Visit[T](IDeclVisitor`1 visitor)
   at CppSharp.AST.AstVisitor.VisitDeclarationContext(DeclarationContext context)
   at CppSharp.AST.AstVisitor.VisitNamespace(Namespace namespace)
   at CppSharp.AST.Namespace.Visit[T](IDeclVisitor`1 visitor)
   at CppSharp.AST.AstVisitor.VisitDeclarationContext(DeclarationContext context)
   at CppSharp.Passes.IgnoreSystemDeclarationsPass.VisitTranslationUnit(TranslationUnit unit)
   at CppSharp.Passes.TranslationUnitPass.VisitLibrary(ASTContext context)
   at CppSharp.Generators.BindingContext.<RunPasses>b__42_0(TranslationUnitPass pass)
   at CppSharp.PassBuilder`1.RunPasses(Action`1 action)
   at CppSharp.Generators.BindingContext.RunPasses()
   at CppSharp.Driver.ProcessCode()
   at CppSharp.ConsoleDriver.Run(ILibrary library)
   at QtTestLib_CppSharp.Program.Main(String[] args) in Program.cs:line 42

I may pass you the header file if you are interested in.

ddobrev commented 7 years ago

Even though we cannot always fix bugs in reasonable time, test cases are always welcome.

tritao commented 7 years ago

Thanks for the report, will check the problem later.

mwallnoefer commented 7 years ago

Okay, I found out that the part

Unhandled declaration kind: ClassScopeFunctionSpecialization
   (line 1)

originates in <xlocnum>, not directly in <string>.

tritao commented 7 years ago

VS 2015 shows up the same warning but does not crash, so I don't think that particular thing is the issue.

Can you see which class is crashing in IgnoreSystemDeclarationsPass.VisitClassDecl(Class class)?

mwallnoefer commented 7 years ago

Since I use the nuget packages please tell me how to enable the debug outputs. Unfortunately, the stacktrace does not reveal more information.

tritao commented 7 years ago

Hmm I am not sure about Nuget package but I assume it should contain debug info.

If it does then it should be possible for you to click on stack trace in VS and check out the contents of the class parameter variable.

ddobrev commented 7 years ago

It actually doesn't, I don't include the PDB-s. Should I?

mwallnoefer commented 7 years ago

I guess the answer is yes, otherwise I cannot provide you with the necessary details.

I provide you with the concerning example project. Basically I tried to expose a Qt library with C++ standard types to C#. QtTestLib.zip