JuliaInterop / CxxWrap.jl

Package to make C++ libraries available in Julia
Other
419 stars 67 forks source link

A little push #76

Closed rveltz closed 7 years ago

rveltz commented 7 years ago

Dear author,

I would like you to give me a little push concerning wrapping the following class. I posted a question on discourse about it and you responded to it. However, I can't manage to even get the constructor working despite copying your code on inheritance.

Loading the module with wrap_modules leads to

ERROR: LoadError: Type 11ProblemBase has no Julia wrapper
Stacktrace:
 [1] load_modules at /Users/rveltz/.julia/v0.6/CxxWrap/src/CxxWrap.jl:141 [inlined]
 [2] wrap_modules at /Users/rveltz/.julia/v0.6/CxxWrap/src/CxxWrap.jl:359 [inlined] (repeats 2 times)
 [3] include_from_node1(::String) at ./loading.jl:569
 [4] include(::String) at ./sysimg.jl:14
 [5] process_options(::Base.JLOptions) at ./client.jl:305
 [6] _start() at ./client.jl:371
while loading /Users/rveltz/work/prog/ddeArndt/wrap-dde.jl, in expression starting on line 4

Can you please give me hint on how to proceed please?

Thank you for your help,

Best regards

#include <cxx_wrap.hpp>
#include "../src/base.h"
#include "../src/problembase.h"
#include "../src/problem.h"
#include "../src/problem-ehl.h"
#include "../src/problem-theune.h"
#include "../src/problem-dreesen.h"
#include "../src/problem-test.h"
#include "../src/string.h"

#include <string>
#include <memory>

#include "jlcxx/jlcxx.hpp"
#include "jlcxx/functions.hpp"

namespace ddesolver
{
    typedef int (*history_f) (double * const  , const double , const double * const , double * );
    typedef int (*history_tau) (double *, double);

    class DDE : public ProblemBase
    {
        public:
            // DDE(ProblemBase *pb);
            DDE(history_f f1,history_tau tau1, int N1, int Nd1){f_=f1;tau_=tau1;N=N1;Nd=Nd1;};
            int tau(double *tau_a, double x){return tau_(tau_a,x);}
            int f(double * const Dy, const double x, const double * const y, double * z = 0){return f_(  Dy,   x,  y, z);}
            void Config()
            {
                cout<<"--> Entry in Config()\n";
                // Dateninitialisierungen (vom Benutzer zu aendern)
                // Kurze Problembeschreibung:
                SetProblemDescription("DDE solver with Julia");
                SetOutputType(matlab);
                SetDimension(N);   // Dimension des Systems
                SetNumberofDelays(Nd);

                SetStartingPoint(0.0);        // initial time-point  t0
                SetOutputFile("PH.m");    // file to save data
                SetStepsize(0.1);            // Initial step size or constant step size
                SetFixedStep(1);              // 1: Constant step size, 0: Step size control
                SetAbsTolerance(1.0e-6);     // Local absolute error tolerance
                SetRelTolerance(GetAbsTolerance()); // Local relative error tolerance
                SetNumberofOutputPoints(100);   // Number of points for output (at least 1) (point of origin not taken in account)
                SetWidth(12);                 // Number of figures which can be output
                SetPrecision(6);             // Number of significant figures
                SetPrintAllSteps(1);          // 1: Gib jeden Schritt aus,  0: nicht
                SetPrintRejected(0);          // 1: Output each step, 0: not
                SetProcedure("Sarafyan56","Hermite_4");
                cout<<"--> Sortie de Config()"<<endl;
            }

            int g(double * const g, const double x){return 0;};
            void SetInitialState()
            {
                // Initialisierungen (vom Benutzer zu aendern)

                // Verwende als Anfangswert den Wert der Anfangsfunktion g(x0)
                g(m_initState, GetStartingPoint());
            }

            history_f f_;
            history_tau tau_; 
            int N, Nd;
            double * initial_condition;
    };
}

namespace jlcxx
{
  template<> struct SuperType<ddesolver::DDE>   { typedef ProblemBase type; };
}

JULIA_CPP_MODULE_BEGIN(registry)
  jlcxx::Module& ddesolver_mod = registry.create_module("DDESolver");
  ddesolver_mod.add_type<ddesolver::DDE>("DDE", jlcxx::julia_type<ProblemBase>()).constructor<ddesolver::history_f,ddesolver::history_tau,int,int>();
JULIA_CPP_MODULE_END
rveltz commented 7 years ago

OK, I think I got it to run with

jlcxx::Module& ddesolver_mod = registry.create_module("DDESolver");
  ddesolver_mod.add_type<ddesolver::DDE>("DDE")
      .constructor<int>()
      .constructor<ddesolver::history_f,ddesolver::history_tau,int,int>()
      .method("solve", &ProblemBase::Solve);

Not sure it is good to remove the type from the second line. This produces the error for which I have no clue since d is not in my code.

ERROR: LoadError: Type d has no Julia wrapper
Stacktrace:
 [1] DDE(::CxxWrap.SafeCFunction, ::CxxWrap.SafeCFunction, ::Int32, ::Int32) at ./<missing>:0
 [2] include_from_node1(::String) at ./loading.jl:569
 [3] include(::String) at ./sysimg.jl:14
 [4] process_options(::Base.JLOptions) at ./client.jl:305
 [5] _start() at ./client.jl:371
while loading /Users/rveltz/work/prog/ddeArndt/wrap-dde.jl, in expression starting on line 29

The julia code leading to this is:

using CxxWrap

@show pwd()
wrap_modules(joinpath(pwd()*"/lib/","libarndtWrap"))

using DDESolver
prob1 = DDESolver.DDE(1)

# typedef int (*history_f) (double * const  , const double , const double * const , double * );
# typedef int (*history_tau) (double *, double);
# MacKeyGlass
Nd = 1
N = 1

function tau(tau_a,t)
    tau_a[1] = 20.0
    return Int32(1)
end

function rhs(Dy, x, y, z)
    lambda = 0.2
    g = 0.1
    am = 1.0
    np = 10
    Dy[1] = -g*y[1] + lambda*am*z[1]/(am+z[1]*z[1]);
    return Int32(0)
end

prob = DDESolver.DDE(safe_cfunction(rhs,Int32,(Ptr{Float64},Float64,Ptr{Float64},Ptr{Float64},)),
                    safe_cfunction(tau,Int32,(Ptr{Float64},Float64,)),
                    Int32(1),Int32(1))
barche commented 7 years ago

Hi,

For the first problem, you need to wrap ProblemBase before using it as a base type, i.e. first do:

ddesolver_mod.add_type<ProblemBase>("ProblemBase");

Type d is double (this can be found using the c++filt -t d shell command, the names are mangled and there is no general way to unmangle them to print a nicer error message). Not sure why it gives that error though, double is of course supported. Is there a non-const reference to double somewhere?

rveltz commented 7 years ago

Thank you!

It seems there are difficulties to wrap const definitions with safe_cfunction. In particular the const double * const z in the type history_f seems to be the cause of the error. I am not sure what to do for this.

barche commented 7 years ago

OK, the const pointer problem was a bug, should be fixed on latest master. To prevent unintentional modification of const data, I mapped it to a CxxWrap.ConstPtr, see the test code here on how to get an array out of it: https://github.com/JuliaInterop/CxxWrap.jl/blob/master/test/functions.jl#L83-L89

rveltz commented 7 years ago

Thank you!!

It works :)

I have a basic wrapper now!!!