From 0b5a8c5de0aebd607875b4df35b56feb63f21dd4 Mon Sep 17 00:00:00 2001
From: Sebastian Gutsche <gutsche@momo.math.rwth-aachen.de>
Date: Tue, 14 May 2019 22:48:52 +0200
Subject: [PATCH] First version of caller - WIP

---
 .gitignore                        |   1 +
 deps/build.jl                     |   3 +
 deps/parselibs.jl                 |  46 ++++
 deps/src/CMakeLists.txt           |   4 +-
 deps/src/caller.cpp               | 358 ++++++++++++++++++++++++++++++
 deps/src/caller.h                 |   8 +
 deps/src/coeffs.cpp               |   7 +-
 deps/src/ideals.cpp               |   4 +-
 deps/src/singular.cpp             |  90 ++++----
 src/LibSingular.jl                |   2 +
 src/Meta.jl                       |  34 +++
 src/Singular.jl                   |  11 +
 src/caller.jl                     | 189 ++++++++++++++++
 src/ideal/ideal.jl                |  20 +-
 src/module/ModuleTypes.jl         |  24 ++
 src/module/module.jl              |  12 +-
 src/number/NumberTypes.jl         |   2 +-
 src/poly/PolyTypes.jl             |   7 +
 src/poly/poly.jl                  |   4 +
 src/resolution/ResolutionTypes.jl |  11 +-
 src/resolution/resolution.jl      |  48 ++--
 test/caller-test.jl               |  46 ++++
 test/runtests.jl                  |  21 +-
 23 files changed, 849 insertions(+), 103 deletions(-)
 create mode 100644 deps/parselibs.jl
 create mode 100644 deps/src/caller.cpp
 create mode 100644 deps/src/caller.h
 create mode 100644 src/Meta.jl
 create mode 100644 src/caller.jl
 create mode 100644 test/caller-test.jl

diff --git a/.gitignore b/.gitignore
index b064b7d66..0ef780992 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@ docs/build
 *.jl.*.cov
 *.jl.mem
 .gitattributes
+/src/libraryfuncdictionary.jl
diff --git a/deps/build.jl b/deps/build.jl
index f6bd3dba4..0a4d72a3a 100644
--- a/deps/build.jl
+++ b/deps/build.jl
@@ -98,6 +98,7 @@ withenv("CPP_FLAGS"=>"-I$vdir/include", "LD_LIBRARY_PATH"=>"$vdir/lib:$nemodir/l
    cmd = split(
      """
      $srcs/configure
+     --with-libparse
      --prefix=$vdir
      --libdir=$vdir/lib
      --disable-static
@@ -152,3 +153,5 @@ print("Running cmake")
 run(`make VERBOSE=1`)
 run(`make install`)
 
+include("parselibs.jl")
+
diff --git a/deps/parselibs.jl b/deps/parselibs.jl
new file mode 100644
index 000000000..2510a9295
--- /dev/null
+++ b/deps/parselibs.jl
@@ -0,0 +1,46 @@
+function execute(cmd::Cmd)
+    out = Pipe()
+    err = Pipe()
+  
+    process = run(pipeline(ignorestatus(cmd), stdout = out, stderr = err))
+    close(out.in)
+    close(err.in)
+  
+    (stdout = String(read(out)), 
+      stderr = String(read(err)),  
+      code = process.exitcode)
+end
+
+libparsepath = abspath(joinpath(@__DIR__, "..", "local", "bin", "libparse"))
+
+library_dir = ""
+
+if haskey(ENV, "SINGULAR_LIBRARY_DIR")
+    library_dir = ENV["SINGULAR_LIBRARY_DIR"]
+else
+    library_dir = abspath(joinpath(@__DIR__, "..", "local", "share", "singular", "LIB"))
+end
+
+filenames = filter(x -> endswith(x, ".lib"), readdir(library_dir))
+
+output_filename = abspath(joinpath(@__DIR__, "..", "src", "libraryfuncdictionary.jl"))
+
+open(output_filename, "w") do outputfile
+    println(outputfile, "libraryfunctiondictionary = Dict(")
+    for i in filenames
+        full_path = joinpath(library_dir, i)
+        libs = execute(`$libparsepath $full_path`)
+        if libs.stderr != ""
+            error("from libparse: $(libs.stderr)")
+        end
+        libs_splitted = split(libs.stdout,"\n")[4:end-1]
+        libs_splitted = [ split(i," ") for i in libs_splitted ]
+        libs_splitted = [ [ j for j in i if j != ""] for i in libs_splitted ]
+        println(outputfile, ":$(i[1:end - 4]) => [")
+        for j in libs_splitted
+            println(outputfile, """[ "$(j[1])", "$(j[3])" ],""")
+        end
+        println(outputfile, "],\n")
+    end
+    println(outputfile, ")\n")
+end
diff --git a/deps/src/CMakeLists.txt b/deps/src/CMakeLists.txt
index acd8e8000..26c9c4d27 100644
--- a/deps/src/CMakeLists.txt
+++ b/deps/src/CMakeLists.txt
@@ -10,10 +10,10 @@ include_directories(${nemo_includes})
 include_directories(${singular_includes})
 include_directories(${singular_includes}/singular)
 
-SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14" )
+SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -g" )
 SET( CMAKE_SHARED_LINKER_FLAGS  "${CMAKE_SHARED_LINKER_FLAGS} -L${JULIA_LIB_DIR} -Wl,-rpath,${JULIA_LIB_DIR} -L${singular_libdir} -Wl,-rpath,${singular_libdir}" )
 
-add_library(singularwrap SHARED singular.cpp rings.cpp coeffs.cpp ideals.cpp matrices.cpp)
+add_library(singularwrap SHARED singular.cpp rings.cpp coeffs.cpp ideals.cpp matrices.cpp caller.cpp)
 target_link_libraries(singularwrap JlCxx::cxxwrap_julia -ljulia "-lSingular -lpolys -lsingular_resources -lfactory -lomalloc -ldl")
 
 install(TARGETS
diff --git a/deps/src/caller.cpp b/deps/src/caller.cpp
new file mode 100644
index 000000000..b606a10a4
--- /dev/null
+++ b/deps/src/caller.cpp
@@ -0,0 +1,358 @@
+#include "caller.h"
+
+#include <Singular/tok.h>
+#include <Singular/grammar.h>
+#include <Singular/ipshell.h>
+#include <Singular/lists.h>
+#include <misc/intvec.h>
+
+// #include <julia/julia.h>
+
+static jl_value_t * jl_int64_vector_type;
+static jl_value_t * jl_int64_matrix_type;
+static jl_value_t * jl_singular_number_type;
+static jl_value_t * jl_singular_poly_type;
+static jl_value_t * jl_singular_ring_type;
+static jl_value_t * jl_singular_ideal_type;
+static jl_value_t * jl_singular_matrix_type;
+static jl_value_t * jl_singular_bigint_type;
+static jl_value_t * jl_singular_bigintmat_type;
+static jl_value_t * jl_singular_map_type;
+static jl_value_t * jl_singular_resolution_type;
+static jl_value_t * jl_singular_vector_type;
+
+static jl_value_t * get_type_mapper()
+{
+    std::vector<std::pair<int, std::string>> types = {
+        std::pair<int, std::string>(BIGINT_CMD, "BIGINT_CMD"),
+        std::pair<int, std::string>(NUMBER_CMD, "NUMBER_CMD"),
+        std::pair<int, std::string>(RING_CMD, "RING_CMD"),
+        std::pair<int, std::string>(POLY_CMD, "POLY_CMD"),
+        std::pair<int, std::string>(IDEAL_CMD, "IDEAL_CMD"),
+        std::pair<int, std::string>(INT_CMD, "INT_CMD"),
+        std::pair<int, std::string>(STRING_CMD, "STRING_CMD"),
+        std::pair<int, std::string>(LIST_CMD, "LIST_CMD"),
+        std::pair<int, std::string>(INTMAT_CMD, "INTMAT_CMD"),
+        std::pair<int, std::string>(BIGINTMAT_CMD, "BIGINTMAT_CMD"),
+        std::pair<int, std::string>(MAP_CMD, "MAP_CMD"),
+        std::pair<int, std::string>(RESOLUTION_CMD, "RESOLUTION_CMD"),
+        std::pair<int, std::string>(MODUL_CMD, "MODUL_CMD"),
+        std::pair<int, std::string>(VECTOR_CMD, "VECTOR_CMD"),
+        std::pair<int, std::string>(INTVEC_CMD, "INTVEC_CMD")};
+
+    jl_array_t * return_array =
+        jl_alloc_array_1d(jl_array_any_type, types.size());
+
+    for (int i = 0; i < types.size(); i++) {
+        jl_array_t * current_return = jl_alloc_array_1d(jl_array_any_type, 2);
+        jl_arrayset(current_return, jl_box_int64(types[i].first), 0);
+        jl_arrayset(current_return,
+                    reinterpret_cast<jl_value_t *>(
+                        jl_symbol(types[i].second.c_str())),
+                    1);
+        jl_arrayset(return_array,
+                    reinterpret_cast<jl_value_t *>(current_return), i);
+    }
+    return reinterpret_cast<jl_value_t *>(return_array);
+}
+
+static void initialize_jl_c_types(jl_value_t * module_value)
+{
+    jl_module_t * module = reinterpret_cast<jl_module_t *>(module_value);
+    jl_int64_vector_type =
+        jl_apply_array_type((jl_value_t *)jl_int64_type, 1);
+    jl_int64_matrix_type =
+        jl_apply_array_type((jl_value_t *)jl_int64_type, 2);
+    jl_singular_number_type = jl_get_global(module, jl_symbol("number"));
+    jl_singular_poly_type = jl_get_global(module, jl_symbol("poly"));
+    jl_singular_ring_type = jl_get_global(module, jl_symbol("ring"));
+    jl_singular_ideal_type = jl_get_global(module, jl_symbol("ideal"));
+    jl_singular_matrix_type = jl_get_global(module, jl_symbol("ip_smatrix"));
+    jl_singular_bigint_type =
+        jl_get_global(module, jl_symbol("__mpz_struct"));
+    jl_singular_bigintmat_type =
+        jl_get_global(module, jl_symbol("bigintmat"));
+    jl_singular_map_type = jl_get_global(module, jl_symbol("sip_smap"));
+    jl_singular_resolution_type =
+        jl_get_global(module, jl_symbol("resolvente"));
+}
+
+static inline void * get_ptr_from_cxxwrap_obj(jl_value_t * obj)
+{
+    return *reinterpret_cast<void **>(obj);
+}
+
+// Safe way
+// void* get_ptr_from_cxxwrap_obj(jl_value_t* obj){
+//     return jl_unbox_voidpointer(jl_get_field(obj,"cpp_object"));
+// }
+
+jl_value_t * intvec_to_jl_array(intvec * v)
+{
+    int          size = v->length();
+    jl_array_t * result = jl_alloc_array_1d(jl_int64_vector_type, size);
+    int *        v_content = v->ivGetVec();
+    for (int i = 0; i < size; i++) {
+        jl_arrayset(result, jl_box_int64(static_cast<int64_t>(v_content[i])),
+                    i);
+    }
+    return reinterpret_cast<jl_value_t *>(result);
+}
+
+jl_value_t * intmat_to_jl_array(intvec * v)
+{
+    int          rows = v->rows();
+    int          cols = v->cols();
+    jl_array_t * result = jl_alloc_array_2d(jl_int64_matrix_type, rows, cols);
+    int64_t * result_ptr = reinterpret_cast<int64_t *> jl_array_data(result);
+    for (int i = 0; i < rows; i++) {
+        for (int j = 0; j < cols; j++) {
+            result_ptr[j + (i * cols)] = IMATELEM(*v, i, j);
+        }
+    }
+    return reinterpret_cast<jl_value_t *>(result);
+}
+
+void * jl_array_to_intvec(jl_value_t * array_val)
+{
+    jl_array_t * array = reinterpret_cast<jl_array_t *>(array_val);
+    int          size = jl_array_len(array);
+    intvec *     result = new intvec(size);
+    int *        result_content = result->ivGetVec();
+    for (int i = 0; i < size; i++) {
+        result_content[i] =
+            static_cast<int>(jl_unbox_int64(jl_arrayref(array, i)));
+    }
+    return reinterpret_cast<void *>(result);
+}
+
+void * jl_array_to_intmat(jl_value_t * array_val)
+{
+    jl_array_t * array = reinterpret_cast<jl_array_t *>(array_val);
+    int          rows = jl_array_dim(array, 0);
+    int          cols = jl_array_dim(array, 1);
+    intvec *     result = new intvec(rows, cols, 0);
+    int64_t * array_data = reinterpret_cast<int64_t *>(jl_array_data(array));
+    int *     vec_data = result->ivGetVec();
+    for (int i = 0; i < cols; i++) {
+        for (int j = 0; j < rows; j++) {
+            IMATELEM(*result, i + 1, j + 1) =
+                static_cast<int>(array_data[j + (i * rows)]);
+        }
+    }
+    return reinterpret_cast<void *>(result);
+}
+
+static void * get_ring_ref(ring r)
+{
+    r->ref++;
+    return reinterpret_cast<void *>(r);
+}
+
+static jl_value_t * copy_polyptr_to_void(poly p, ring r)
+{
+    poly p_copy = p_Copy(p, r);
+    return jl_box_voidpointer(reinterpret_cast<void *>(p_copy));
+}
+
+static jl_value_t * copy_idealptr_to_void(ideal i, ring r)
+{
+    ideal i_copy = id_Copy(i, r);
+    return jl_box_voidpointer(reinterpret_cast<void *>(i_copy));
+}
+
+static void * copy_string_to_void(std::string s)
+{
+    return reinterpret_cast<void *>(omStrDup(s.c_str()));
+}
+
+bool translate_singular_type(jl_value_t * obj,
+                             void **      args,
+                             int *        argtypes,
+                             int          i)
+{
+    jl_array_t * array = reinterpret_cast<jl_array_t *>(obj);
+    int    cmd = static_cast<int>(jl_unbox_int64(jl_arrayref(array, 0)));
+    void * arg = jl_unbox_voidpointer(jl_arrayref(array, 1));
+    args[i] = arg;
+    argtypes[i] = cmd;
+    return true;
+}
+
+jl_value_t * get_julia_type_from_sleftv(leftv ret)
+{
+    jl_array_t * result = jl_alloc_array_1d(jl_array_any_type, 3);
+    jl_arrayset(result, jl_false, 0);
+    jl_arrayset(result, jl_box_voidpointer(ret->data), 1);
+    ret->data = 0;
+    jl_arrayset(result, jl_box_int64(ret->Typ()), 2);
+    ret->rtyp = 0;
+    return reinterpret_cast<jl_value_t *>(result);
+}
+
+jl_value_t * get_ring_content(ring r)
+{
+    // count elements
+    idhdl h = r->idroot;
+    int   nr = 0;
+    while (h != NULL) {
+        nr++;
+        h = IDNEXT(h);
+    }
+    jl_array_t * result = jl_alloc_array_1d(jl_array_any_type, nr);
+    h = r->idroot;
+    nr = 0;
+    while (h != NULL) {
+        jl_array_t * current = jl_alloc_array_1d(jl_array_any_type, 3);
+        jl_arrayset(current, jl_box_int64(IDTYP(h)), 0);
+        jl_arrayset(current,
+                    reinterpret_cast<jl_value_t *>(jl_symbol(IDID(h))), 1);
+        jl_arrayset(current, jl_box_voidpointer(IDDATA(h)), 2);
+        jl_arrayset(result, reinterpret_cast<jl_value_t *>(current), nr);
+        h = IDNEXT(h);
+        nr++;
+    }
+    return reinterpret_cast<jl_value_t *>(result);
+}
+
+jl_value_t * call_singular_library_procedure(
+    std::string s, ring r, jlcxx::ArrayRef<jl_value_t *> arguments)
+{
+    int    len = arguments.size();
+    void * args[len];
+    int    argtypes[len + 1];
+    argtypes[len] = 0;
+    for (int i = 0; i < len; i++) {
+        bool result =
+            translate_singular_type(arguments[i], args, argtypes, i);
+        if (!result) {
+            jl_error("Could not convert argument");
+        }
+    }
+    BOOLEAN      err;
+    jl_value_t * retObj;
+    leftv        ret = ii_CallLibProcM(s.c_str(), args, argtypes, r, err);
+    if (err) {
+        jl_error("Could not call function");
+    }
+    if (ret->next != NULL) {
+        int          len = ret->listLength();
+        jl_array_t * list = jl_alloc_array_1d(jl_array_any_type, len + 1);
+        jl_arrayset(list, jl_true, 0);
+        for (int i = 0; i < len; ++i) {
+            leftv next = ret->next;
+            ret->next = 0;
+            jl_arrayset(list, get_julia_type_from_sleftv(ret), i + 1);
+            if (i > 0)
+                omFreeBin(ret, sleftv_bin);
+            ret = next;
+        }
+        retObj = reinterpret_cast<jl_value_t *>(list);
+    }
+    else {
+        retObj = get_julia_type_from_sleftv(ret);
+        omFreeBin(ret, sleftv_bin);
+    }
+    return retObj;
+}
+
+jl_value_t * call_singular_library_procedure_wo_ring(
+    std::string name, jlcxx::ArrayRef<jl_value_t *> arguments)
+{
+    return call_singular_library_procedure(name, NULL, arguments);
+}
+
+jl_value_t * convert_nested_list(void * l_void)
+{
+    lists        l = reinterpret_cast<lists>(l_void);
+    int          len = lSize(l) + 1;
+    jl_array_t * result_array = jl_alloc_array_1d(jl_array_any_type, len);
+    for (int i = 0; i < len; i++) {
+        leftv current = &(l->m[i]);
+        if (current->Typ() == LIST_CMD) {
+            jl_arrayset(
+                result_array,
+                convert_nested_list(reinterpret_cast<void *>(current->data)),
+                i);
+        }
+        else {
+            jl_arrayset(result_array, get_julia_type_from_sleftv(current), i);
+        }
+    }
+    return reinterpret_cast<jl_value_t *>(result_array);
+}
+
+void * create_syStrategy_data(syStrategy res, ring o)
+{
+    const ring origin = currRing;
+    rChangeCurrRing(o);
+    syStrategy temp = syCopy(res);
+    rChangeCurrRing(origin);
+    return reinterpret_cast<void *>(temp);
+}
+
+void singular_define_caller(jlcxx::Module & Singular)
+{
+    Singular.method("load_library", [](std::string name) {
+        char * plib = iiConvName(name.c_str());
+        idhdl  h = ggetid(plib);
+        omFree(plib);
+        if (h == NULL) {
+            BOOLEAN bo = iiLibCmd(omStrDup(name.c_str()), TRUE, TRUE, FALSE);
+            if (bo)
+                return jl_false;
+        }
+        return jl_true;
+    });
+    Singular.method("call_singular_library_procedure",
+                    &call_singular_library_procedure);
+    Singular.method("call_singular_library_procedure",
+                    &call_singular_library_procedure_wo_ring);
+    Singular.method("get_type_mapper", &get_type_mapper);
+    Singular.method("initialize_jl_c_types", &initialize_jl_c_types);
+
+
+    Singular.method("NUMBER_CMD_CASTER",
+                    [](void * obj) { return reinterpret_cast<number>(obj); });
+    Singular.method("RING_CMD_CASTER",
+                    [](void * obj) { return reinterpret_cast<ring>(obj); });
+    Singular.method("POLY_CMD_CASTER",
+                    [](void * obj) { return reinterpret_cast<poly>(obj); });
+    Singular.method("IDEAL_CMD_CASTER",
+                    [](void * obj) { return reinterpret_cast<ideal>(obj); });
+    Singular.method("INT_CMD_CASTER", [](void * obj) {
+        return jl_box_int64(reinterpret_cast<long>(obj));
+    });
+    Singular.method("STRING_CMD_CASTER", [](void * obj) {
+        return std::string(reinterpret_cast<char *>(obj));
+    });
+    Singular.method("INTVEC_CMD_CASTER", [](void * obj) {
+        return intvec_to_jl_array(reinterpret_cast<intvec *>(obj));
+    });
+    Singular.method("INTMAT_CMD_CASTER", [](void * obj) {
+        return intmat_to_jl_array(reinterpret_cast<intvec *>(obj));
+    });
+    Singular.method("BIGINT_CMD_CASTER", [](void * obj) {
+        return reinterpret_cast<__mpz_struct *>(obj);
+    });
+    Singular.method("BIGINTMAT_CMD_CASTER", [](void * obj) {
+        return reinterpret_cast<bigintmat *>(obj);
+    });
+    Singular.method("MAP_CMD_CASTER", [](void * obj) {
+        return reinterpret_cast<sip_smap *>(obj);
+    });
+    Singular.method("RESOLUTION_CMD_CASTER", [](void * obj) {
+        return reinterpret_cast<syStrategy>(obj);
+    });
+    Singular.method("LIST_CMD_TRAVERSAL", &convert_nested_list);
+    Singular.method("get_ring_content", &get_ring_content);
+    Singular.method("get_ring_ref", &get_ring_ref);
+    Singular.method("copy_polyptr_to_void", &copy_polyptr_to_void);
+    Singular.method("copy_idealptr_to_void", &copy_idealptr_to_void);
+    Singular.method("jl_array_to_intvec", &jl_array_to_intvec);
+    Singular.method("jl_array_to_intmat", &jl_array_to_intmat);
+    Singular.method("copy_string_to_void", &copy_string_to_void);
+
+    Singular.method("create_syStrategy_data", &create_syStrategy_data);
+
+}
diff --git a/deps/src/caller.h b/deps/src/caller.h
new file mode 100644
index 000000000..bf49c67da
--- /dev/null
+++ b/deps/src/caller.h
@@ -0,0 +1,8 @@
+#ifndef CALLER_INCLUDE
+#define CALLER_INCLUDE
+
+#include "includes.h"
+
+void singular_define_caller(jlcxx::Module &);
+
+#endif
diff --git a/deps/src/coeffs.cpp b/deps/src/coeffs.cpp
index 7d1ded8ae..b7457f2b3 100644
--- a/deps/src/coeffs.cpp
+++ b/deps/src/coeffs.cpp
@@ -44,11 +44,10 @@ void singular_define_coeffs(jlcxx::Module & Singular)
         }
     });
 
-    Singular.method("n_Delete_Q", [](void * n, coeffs cf) {
-        number   tt = reinterpret_cast<number>(n);
-        number * t = &tt;
+    Singular.method("n_Delete_Q", [](snumber * n, coeffs cf) {
+        ;
         if (n != NULL) {
-            n_Delete(t, cf);
+            n_Delete(&n, cf);
         }
     });
 
diff --git a/deps/src/ideals.cpp b/deps/src/ideals.cpp
index a174bc635..05cc9f2a3 100644
--- a/deps/src/ideals.cpp
+++ b/deps/src/ideals.cpp
@@ -12,7 +12,7 @@ auto id_sres_helper(sip_sideal * m, int n, ring R)
         r = s->fullres;
         minimal = false;
     }
-    return std::make_tuple(reinterpret_cast<void *>(r), s->length, minimal);
+    return std::make_tuple(s, minimal);
 }
 
 
@@ -28,7 +28,7 @@ auto id_fres_helper(sip_sideal * I, int n, std::string method, ring R)
         r = s->fullres;
         minimal = false;
     }
-    return std::make_tuple(reinterpret_cast<void *>(r), s->length, minimal);
+    return std::make_tuple(s, minimal);
 }
 
 
diff --git a/deps/src/singular.cpp b/deps/src/singular.cpp
index 932d424b1..f3fef6fc6 100644
--- a/deps/src/singular.cpp
+++ b/deps/src/singular.cpp
@@ -4,6 +4,7 @@
 #include "rings.h"
 #include "ideals.h"
 #include "matrices.h"
+#include "caller.h"
 
 static std::string singular_return;
 static std::string singular_error;
@@ -48,6 +49,7 @@ JLCXX_MODULE define_julia_module(jlcxx::Module & Singular)
     Singular.add_type<ip_smatrix>("ip_smatrix");
     Singular.add_type<ssyStrategy>("syStrategy");
     Singular.add_type<sip_smap>("sip_smap");
+    Singular.add_type<bigintmat>("bigintmat");
 
     /* monomial orderings */
     Singular.set_const("ringorder_no", ringorder_no);
@@ -73,6 +75,7 @@ JLCXX_MODULE define_julia_module(jlcxx::Module & Singular)
     singular_define_rings(Singular);
     singular_define_ideals(Singular);
     singular_define_matrices(Singular);
+    singular_define_caller(Singular);
 
 
     // Calls the Singular interpreter with `input`.
@@ -124,60 +127,69 @@ JLCXX_MODULE define_julia_module(jlcxx::Module & Singular)
      ** from resolutions.jl
      ***************************/
 
-    Singular.method("res_Delete_helper", [](void * ra_void, int len, ring o) {
-        auto ra = reinterpret_cast<resolvente>(ra_void);
-        for (int i = 0; i < len; i++) {
-            id_Delete(ra + i, o);
-        }
-        omFreeSize((ADDRESS)ra, (len + 1) * sizeof(ideal));
-    });
+    Singular.method("res_Delete_helper",
+                    [](syStrategy ra, ring o) { syKillComputation(ra, o); });
 
-    Singular.method("res_Copy", [](void * ra_void, int len, ring o) {
-        auto       ra = reinterpret_cast<resolvente>(ra_void);
-        resolvente res = (resolvente)omAlloc0((len + 1) * sizeof(ideal));
+    Singular.method("res_Copy", [](syStrategy ra, ring o) {
+        const ring origin = currRing;
         rChangeCurrRing(o);
-        for (int i = len - 1; i >= 0; i--) {
-            if (ra[i] != NULL)
-                res[i] = id_Copy(ra[i], o);
-        }
-        return reinterpret_cast<void *>(res);
+        syStrategy temp = syCopy(ra);
+        rChangeCurrRing(origin);
+        return temp;
     });
 
+    Singular.method("getindex_internal",
+                    [](syStrategy ra, int64_t k, bool minimal) {
+                        if (minimal) {
+                            return ra->minres[k];
+                        }
+                        return (ideal)ra->fullres[k];
+                    });
 
-    Singular.method("getindex", [](void * ra_void, int k) {
-        auto ra = reinterpret_cast<resolvente>(ra_void);
-        return (ideal)ra[k];
-    });
-
-    Singular.method("syMinimize", [](void * ra_void, int len, ring o) {
-        auto       ra = reinterpret_cast<resolvente>(ra_void);
+    Singular.method("syMinimize", [](syStrategy ra, ring o) {
         const ring origin = currRing;
-        syStrategy temp = (syStrategy)omAlloc0(sizeof(ssyStrategy));
-        resolvente result;
         rChangeCurrRing(o);
-        temp->fullres = (resolvente)omAlloc0((len + 1) * sizeof(ideal));
-        for (int i = len - 1; i >= 0; i--) {
-            if (ra[i] != NULL)
-                temp->fullres[i] = idCopy(ra[i]);
-        }
-        temp->length = len;
+        syStrategy temp = syCopy(ra);
         syMinimize(temp);
-        result = temp->minres;
-        temp->minres = NULL;
-        // syMinimize increments this as it returns a value we ignore
-        temp->references--;
-        syKillComputation(temp, o);
         rChangeCurrRing(origin);
-        return reinterpret_cast<void *>(result);
+        return reinterpret_cast<void *>(temp);
     });
 
+    Singular.method("get_minimal_res", [](syStrategy ra) {
+        return reinterpret_cast<void *>(ra->minres);
+    });
+
+    Singular.method("get_full_res", [](syStrategy ra) {
+        return reinterpret_cast<void *>(ra->fullres);
+    });
+
+    Singular.method("get_sySize", [](syStrategy ra) {
+        return static_cast<int64_t>(sySize(ra));
+    });
+
+    Singular.method("create_SyStrategy", [](void * res_void, int64_t len,
+                                            ring r) {
+        resolvente res = reinterpret_cast<resolvente>(res_void);
+        syStrategy result = (syStrategy)omAlloc0(sizeof(ssyStrategy));
+        result->list_length = static_cast<short>(len);
+        result->length = static_cast<int>(len);
+        resolvente res_cp = (resolvente)omAlloc0((len + 1) * sizeof(ideal));
+        for (int i = 0; i <= len; i++) {
+            if (res[i] != NULL) {
+                res_cp[i] = id_Copy(res[i], r);
+            }
+        }
+        result->fullres = res_cp;
+        result->syRing = r;
+        return result;
+    });
 
-    Singular.method("syBetti", [](void * ra_void, int len, ring o) {
-        auto       ra = reinterpret_cast<resolvente>(ra_void);
+    Singular.method("syBetti_internal", [](void * ra, int len, ring o) {
         const ring origin = currRing;
         rChangeCurrRing(o);
         int      dummy;
-        intvec * iv = syBetti(ra, len, &dummy, NULL, FALSE, NULL);
+        intvec * iv = syBetti(reinterpret_cast<resolvente>(ra), len, &dummy,
+                              NULL, FALSE, NULL);
         rChangeCurrRing(origin);
         int  nrows = iv->rows();
         int  ncols = iv->cols();
diff --git a/src/LibSingular.jl b/src/LibSingular.jl
index 7d6d1d9b5..5f4ec47de 100644
--- a/src/LibSingular.jl
+++ b/src/LibSingular.jl
@@ -1,11 +1,13 @@
 module libSingular
 
 import Libdl
+
 using CxxWrap
 @wrapmodule(realpath(joinpath(@__DIR__, "..", "local", "lib", "libsingularwrap." * Libdl.dlext)))
 
 function __init__()
    @initcxx
+   initialize_jl_c_types(@__MODULE__)
 end
 
 include("libsingular/LibSingularTypes.jl")
diff --git a/src/Meta.jl b/src/Meta.jl
new file mode 100644
index 000000000..67141de9f
--- /dev/null
+++ b/src/Meta.jl
@@ -0,0 +1,34 @@
+include("libraryfuncdictionary.jl")
+
+input_manipulator_funcs = Dict(
+    :dummy => Dict(
+        # :dummy => i->[ x + 1 for x in i]
+    )
+)
+
+output_manipulator_funcs = Dict(
+    :dummy => Dict(
+        # :dummy => i -> i + 1
+    )
+)
+
+for (name,funcs) in libraryfunctiondictionary
+    name_caps = Symbol( "Lib" * uppercasefirst(string(name)))
+    func_calls = Any[]
+    name_string = string(name) * ".lib"
+    for i in funcs
+        if i[1] == "g"
+            func_name = i[2]
+            symb = Symbol(func_name)
+            input_manipulator = haskey(input_manipulator_funcs,name) && haskey(input_manipulator_funcs[name],symb) ? input_manipulator_funcs[name][symb] : identity
+            output_manipulator = haskey(output_manipulator_funcs,name) && haskey(output_manipulator_funcs[name],symb) ? output_manipulator_funcs[name][symb] : identity
+            push!(func_calls, :($symb(args...) = $(output_manipulator)(low_level_caller($(name_string),$func_name,$(input_manipulator)(args)...)) ))
+            push!(func_calls, :($symb(ring::PolyRing,args...) = $(output_manipulator)(low_level_caller_rng($(name_string),$func_name,ring,$(input_manipulator)(args)...)) ))
+        end
+    end
+    eval(:(baremodule $name_caps
+        import ..Singular: PolyRing, low_level_caller, low_level_caller_rng
+        import Base: *
+        $(func_calls...)
+    end))
+end
diff --git a/src/Singular.jl b/src/Singular.jl
index 1b9e08f01..5486f01f8 100644
--- a/src/Singular.jl
+++ b/src/Singular.jl
@@ -47,6 +47,9 @@ const libsingular = joinpath(pkgdir, "local", "lib", "libSingular")
 
 prefix = realpath(joinpath(@__DIR__, "..", "local"))
 
+mapping_types = nothing
+mapping_types_reversed = nothing
+
 function __init__()
 
    # Initialise Singular
@@ -90,6 +93,10 @@ function __init__()
      :comp1max => ringorder_c,
      :comp1min => ringorder_C
    )
+   global mapping_types, mapping_types_reversed, casting_functions
+   mapping_types = Dict( i[1] => i[2] for i in libSingular.get_type_mapper() )
+   mapping_types_reversed = Dict( j => i for (i, j) in mapping_types )
+   casting_functions = create_casting_functions()
 end
 
 ###############################################################################
@@ -116,4 +123,8 @@ include("Vector.jl")
 
 include("Resolution.jl")
 
+include("caller.jl")
+
+include("Meta.jl")
+
 end # module
diff --git a/src/caller.jl b/src/caller.jl
new file mode 100644
index 000000000..d2e4d2438
--- /dev/null
+++ b/src/caller.jl
@@ -0,0 +1,189 @@
+
+function recursive_translate(x, R)
+    if length(x) > 0 && x[1] isa Bool
+        return convert_return_list(x, R)
+    else
+        return [ recursive_translate(i, R) for i in x]
+    end
+end
+
+# function LIST_CMD_CASTER(x)
+#     x_new = LIST_CMD_TRAVERSAL(x)
+# end
+
+casting_functions_pre = Dict(:NUMBER_CMD     => (libSingular.NUMBER_CMD_CASTER,     true, ()),
+    :RING_CMD       => (libSingular.RING_CMD_CASTER,       false, ()),
+    :POLY_CMD       => (libSingular.POLY_CMD_CASTER,       true, ()),
+    :IDEAL_CMD      => (libSingular.IDEAL_CMD_CASTER,      true, ()),
+    :MODUL_CMD      => (libSingular.IDEAL_CMD_CASTER,      true, (:module,)),
+    :VECTOR_CMD     => (libSingular.POLY_CMD_CASTER,       true, (:vector,)),
+    :INT_CMD        => (libSingular.INT_CMD_CASTER,        false, ()),
+    :STRING_CMD     => (libSingular.STRING_CMD_CASTER,     false, ()),
+    :LIST_CMD       => (libSingular.LIST_CMD_TRAVERSAL,    false, ()),
+    :INTVEC_CMD     => (libSingular.INTVEC_CMD_CASTER,     false, ()),
+    :INTMAT_CMD     => (libSingular.INTMAT_CMD_CASTER,     false, ()),
+    :BIGINT_CMD     => (libSingular.BIGINT_CMD_CASTER,     false, ()),
+    :BIGINTMAT_CMD  => (libSingular.BIGINTMAT_CMD_CASTER,  false, ()),
+    :MAP_CMD        => (libSingular.MAP_CMD_CASTER,        false, ()),
+    :RESOLUTION_CMD => (libSingular.RESOLUTION_CMD_CASTER, true, (:resolution,)))
+
+casting_functions = nothing
+
+function create_casting_functions()
+    pair_array = Any[]
+    for (sym, func) in casting_functions_pre
+        push!(pair_array, mapping_types_reversed[sym] => func)
+    end
+    return Dict(pair_array...)
+end
+
+function convert_ring_content(value_list, rng)
+    return_dict = Dict{Symbol,Any}()
+    for i in value_list
+        return_dict[i[2]] = convert_return_value([false,i[3],i[1]], rng)
+    end
+    return return_dict
+end
+
+function convert_return_value(single_value, rng = nothing)
+    if single_value[1]
+        error("recieved list instead of single value")
+    end
+    cast = casting_functions[single_value[3]][1](single_value[2])
+    if cast isa Array{Any}
+        return recursive_translate(cast, rng)
+    elseif cast isa libSingular.ring
+        new_ring = rng(cast)
+        return [ new_ring, convert_ring_content(libSingular.get_ring_content(cast), new_ring) ]
+    elseif casting_functions[single_value[3]][2]
+        if length(casting_functions[single_value[3]][3]) > 0
+            cast = rng(cast, Val(casting_functions[single_value[3]][3][1]))
+        else
+            cast = rng(cast)
+        end
+    end
+    return cast
+end
+
+
+function convert_return_list(list_value, ring = nothing)
+    if list_value[1]
+        return map(i -> convert_return_value(i, ring), list_value[2:end])
+    end
+    return convert_return_value(list_value, ring)
+end
+
+function get_ring(arg_list)
+    ring = nothing
+    for i in arg_list
+        current_ptr = nothing
+        try
+            current_ptr = i.ptr
+        catch
+            continue
+        end
+        if current_ptr isa poly
+            return parent(i)
+        elseif current_ptr isa ideal
+            return parent(i).base_ring
+        end
+    end
+    return ring
+end
+
+function prepare_argument(x::Array{Int64,1})
+    return Any[ mapping_types_reversed[:INTVEC_CMD], libSingular.jl_array_to_intvec(x) ], nothing
+end
+
+function prepare_argument(x::Array{Int64,2})
+    return Any[ mapping_types_reversed[:INTMAT_CMD], libSingular.jl_array_to_intmat(x) ], nothing
+end
+
+function prepare_argument(x::Int64)
+    return Any[ mapping_types_reversed[:INT_CMD], Ptr{Cvoid}(x) ], nothing
+end
+
+function prepare_argument(x::String)
+    return Any[ mapping_types_reversed[:STRING_CMD], libSingular.copy_string_to_void(x) ], nothing
+end
+
+function prepare_argument(x::PolyRing)
+    new_ptr = libSingular.get_ring_ref(x.ptr)
+    return Any[ mapping_types_reversed[:RING_CMD], new_ptr ], x
+end
+
+function prepare_argument(x::spoly)
+    rng = parent(x)
+    rng_ptr = rng.ptr
+    return Any[ mapping_types_reversed[:POLY_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng_ptr) ], rng
+end
+
+function prepare_argument(x::svector)
+    rng = parent(x).base_ring
+    rng_ptr = rng.ptr
+    return Any[ mapping_types_reversed[:VECTOR_CMD], libSingular.copy_polyptr_to_void(x.ptr, rng_ptr) ], rng
+end
+
+function prepare_argument(x::sideal)
+    rng = parent(x).base_ring
+    rng_ptr = rng.ptr
+    return Any[ mapping_types_reversed[:IDEAL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng_ptr)], rng
+end
+
+function prepare_argument(x::smodule)
+    rng = parent(x).base_ring
+    rng_ptr = rng.ptr
+    return Any[ mapping_types_reversed[:MODUL_CMD], libSingular.copy_idealptr_to_void(x.ptr, rng_ptr)], rng
+end
+
+function prepare_argument(x::sresolution)
+    rng = base_ring(x)
+    res = Any[ mapping_types_reversed[:RESOLUTION_CMD], libSingular.create_syStrategy_data(x.ptr, rng.ptr) ]
+    return res, rng
+end
+
+function prepare_argument(x::Any)
+    if x.ptr isa libSingular.number
+        ptr = x.ptr
+        rng = parent(x)
+        new_ptr = libSingular.n_Copy(ptr, rng.ptr)
+        return Any[ mapping_types_reversed[:NUMBER_CMD], new_ptr.cpp_object ], nothing
+    elseif x.ptr isa libSingular.ip_smatrix
+        rng = parent(x)
+        return Any[ mapping_types_reversed[:MATRIX_CMD], libSingular.mpCopy(x.ptr, rng.ptr).cpp_object ], rng
+    elseif x.ptr isa libSingular.__mpz_struct
+        return Any[ mapping_types_reversed[:BIGINT_CMD], x.ptr.cpp_object ], nothing
+    elseif x.ptr isa libSingular.sip_smap
+        return Any[ mapping_types_reversed[:MAP_CMD], x.ptr.cpp_object ], nothing
+    elseif x.ptr isa libSingular.bigintmat
+        return Any[ mapping_types_reversed[:BIGINTMAT_CMD], x.ptr.cpp_object ], nothing
+    end
+
+end
+
+function low_level_caller_rng(lib::String, name::String, ring, args...)
+    libSingular.load_library(lib)
+    arguments = [prepare_argument(i) for i in args]
+    arguments = Any[ i for (i, j) in arguments ]
+    return_value = libSingular.call_singular_library_procedure(name, ring.ptr, arguments)
+    return convert_return_list(return_value, ring)
+end
+
+function low_level_caller(lib::String, name::String, args...)
+    libSingular.load_library(lib)
+    arguments = [prepare_argument(i) for i in args]
+    rng = nothing
+    for (i, j) in arguments
+        if j != nothing
+            rng = j
+        end
+    end
+    arguments = Any[ i for (i, j) in arguments ]
+    return_values = nothing
+    if rng == nothing
+        return_value = libSingular.call_singular_library_procedure(name, arguments)
+    else
+        return_value = libSingular.call_singular_library_procedure(name, rng.ptr, arguments)
+    end
+    return convert_return_list(return_value, rng)
+end
diff --git a/src/ideal/ideal.jl b/src/ideal/ideal.jl
index 38984d9b1..418301488 100644
--- a/src/ideal/ideal.jl
+++ b/src/ideal/ideal.jl
@@ -484,8 +484,8 @@ function fres(id::Union{sideal{T}, smodule{T}}, max_length::Int, method::String
          && method != "single module")
       error("wrong optional argument for fres")
    end
-   r, length, minimal = libSingular.id_fres(id.ptr, Cint(max_length + 1), method, R.ptr)
-   return sresolution{T}(R, Int(length), r, minimal)
+   r, minimal = libSingular.id_fres(id.ptr, Cint(max_length + 1), method, R.ptr)
+   return sresolution{T}(R, r, minimal)
 end
 
 @doc Markdown.doc"""
@@ -503,16 +503,8 @@ function sres(I::sideal{T}, max_length::Int) where T <: Nemo.RingElem
         max_length = nvars(R)
         # TODO: consider qrings
    end
-   r, length, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr)
-   for i = 1:length
-      ptr = libSingular.getindex(r, Cint(i - 1))
-      if ptr.cpp_object == C_NULL
-         length = i - 1
-         break
-      end
-     libSingular.idSkipZeroes(ptr)
-   end
-   return sresolution{T}(R, length, r, minimal)
+   r, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr)
+   return sresolution{T}(R, r, minimal)
 end
 
 ###############################################################################
@@ -536,6 +528,10 @@ function Ideal(R::PolyRing{T}, id::libSingular.ideal) where T <: Nemo.RingElem
    return sideal{S}(R, id)
 end
 
+function (R::PolyRing{T})(id::libSingular.ideal) where T <: Nemo.RingElem
+    return Ideal(R,id)
+end
+
 # maximal ideal in degree d
 function MaximalIdeal(R::PolyRing{T}, d::Int) where T <: Nemo.RingElem
    (d > typemax(Cint) || d < 0) && throw(DomainError())
diff --git a/src/module/ModuleTypes.jl b/src/module/ModuleTypes.jl
index 7d881d054..d6fb2b0ca 100644
--- a/src/module/ModuleTypes.jl
+++ b/src/module/ModuleTypes.jl
@@ -32,6 +32,18 @@ mutable struct svector{T <: Nemo.RingElem} <: Nemo.ModuleElem{T}
    end
 end
 
+"""
+    (R::PolyRing{T})(m::libSingular.poly,::Val{:vector}) where T
+
+If R is called with a low-level poly pointer, along with
+Val(:vector), it will interpret the poly pointer as a vector.
+This needs to be indicated due to the fact that Singulars
+vectors and polys are both stored in the poly data structure.
+"""
+function (R::PolyRing{T})(m::libSingular.poly,::Val{:vector}) where T
+    return svector{T}(R,1,m)
+end
+
 function _svector_clear_fn(p::svector)
    R = p.base_ring
    libSingular.p_Delete(p.ptr, R.ptr)
@@ -88,6 +100,18 @@ mutable struct smodule{T <: Nemo.RingElem} <: Module{T}
    end
 end
 
+"""
+    (R::PolyRing{T})(m::libSingular.ideal,::Val{:module}) where T
+
+If R is called with a low-level ideal pointer, along with
+Val(:module), it will interpret the ideal pointer as a module.
+This needs to be indicated due to the fact that Singulars
+modules and ideals are both stored in the ideal data structure.
+"""
+function (R::PolyRing{T})(m::libSingular.ideal,::Val{:module}) where T
+    return smodule{T}(R,m)
+end
+
 function _smodule_clear_fn(I::smodule)
    R = I.base_ring
    libSingular.id_Delete(I.ptr, R.ptr)
diff --git a/src/module/module.jl b/src/module/module.jl
index 891794fb1..cf4174260 100644
--- a/src/module/module.jl
+++ b/src/module/module.jl
@@ -160,16 +160,8 @@ function sres(I::smodule{T}, max_length::Int) where T <: Nemo.RingElem
         max_length = nvars(R)
         # TODO: consider qrings
    end
-   r, length, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr)
-   for i = 1:length
-      ptr = libSingular.getindex(r, Cint(i - 1))
-      if ptr.cpp_object == C_NULL
-         length = i - 1
-         break
-      end
-     libSingular.idSkipZeroes(ptr)
-   end
-   return sresolution{T}(R, length, r, minimal)
+   r, minimal = libSingular.id_sres(I.ptr, Cint(max_length + 1), R.ptr)
+   return sresolution{T}(R, r, minimal)
 end
 
 ###############################################################################
diff --git a/src/number/NumberTypes.jl b/src/number/NumberTypes.jl
index 6f4051eec..ce94b02fb 100644
--- a/src/number/NumberTypes.jl
+++ b/src/number/NumberTypes.jl
@@ -133,7 +133,7 @@ end
 
 function _n_Q_clear_fn(n::n_Q)
    R = parent(n)
-   libSingular.n_Delete_Q(n.ptr.cpp_object, parent(n).ptr)
+   libSingular.n_Delete_Q(n.ptr, parent(n).ptr)
    _Rationals_clear_fn(R)
    nothing
 end
diff --git a/src/poly/PolyTypes.jl b/src/poly/PolyTypes.jl
index f4e2f7391..1622c053b 100644
--- a/src/poly/PolyTypes.jl
+++ b/src/poly/PolyTypes.jl
@@ -63,6 +63,13 @@ mutable struct PolyRing{T <: Nemo.RingElem} <: Nemo.MPolyRing{T}
    end
 end
 
+function (R::PolyRing{T})(r::libSingular.ring) where T
+    new_r = deepcopy(R)
+    new_ptr = new_r.ptr
+    new_r.ptr = r
+    return new_r
+end
+
 function _PolyRing_clear_fn(R::PolyRing)
    R.refcount -= 1
    if R.refcount == 0
diff --git a/src/poly/poly.jl b/src/poly/poly.jl
index c1658e6eb..9546d7a22 100644
--- a/src/poly/poly.jl
+++ b/src/poly/poly.jl
@@ -813,6 +813,10 @@ function (R::PolyRing)(p::spoly)
    return p
 end
 
+function(R::PolyRing)(n::libSingular.number)
+    return R.base_ring(n)
+end
+
 ###############################################################################
 #
 #   PolynomialRing constructor
diff --git a/src/resolution/ResolutionTypes.jl b/src/resolution/ResolutionTypes.jl
index 9e27bba62..194ad07e9 100644
--- a/src/resolution/ResolutionTypes.jl
+++ b/src/resolution/ResolutionTypes.jl
@@ -19,22 +19,21 @@ mutable struct ResolutionSet{T <: Nemo.RingElem} <: Set
 end
 
 mutable struct sresolution{T <: Nemo.RingElem} <: Nemo.SetElem
-   ptr::Ptr{Nothing}
-   len::Int
+   ptr::libSingular.syStrategyRef
    minimal::Bool
    base_ring::PolyRing
 
    # really takes a Singular module, which has type ideal
-   function sresolution{T}(R::PolyRing, n::Int, ptr::Ptr{Nothing}, minimal::Bool=false) where T
+   function sresolution{T}(R::PolyRing, ptr::libSingular.syStrategy, minimal::Bool=false) where T
       R.refcount += 1
-      z = new(ptr, n, minimal, R)
+      z = new(ptr, minimal, R)
       finalizer(_sresolution_clear_fn, z)
       return z
    end
 end
 
 function _sresolution_clear_fn(r::sresolution)
-   R = base_ring(r)
-   libSingular.res_Delete_helper(r.ptr, Cint(r.len), R.ptr)
+    R = base_ring(r)
+    libSingular.res_Delete_helper(r.ptr, R.ptr)
     _PolyRing_clear_fn(R)
 end
diff --git a/src/resolution/resolution.jl b/src/resolution/resolution.jl
index 87416acf5..0290360f1 100644
--- a/src/resolution/resolution.jl
+++ b/src/resolution/resolution.jl
@@ -21,13 +21,13 @@ elem_type(::ResolutionSet{T}) where T <: AbstractAlgebra.RingElem = sresolution{
 parent_type(::Type{sresolution{T}}) where T <: AbstractAlgebra.RingElem = ResolutionSet{T}
 
 function checkbounds(r::sresolution, i::Int)
-   (i < 1 || i > r.len) && throw(BoundsError(I, i))
+   (i < 1 || i > libSingular.get_sySize(r.ptr)) && throw(BoundsError(r, i))
 end
 
 function getindex(r::sresolution, i::Int)
    checkbounds(r, i)
    R = base_ring(r)
-   ptr = libSingular.getindex(r.ptr, Cint(i - 1))
+   ptr = libSingular.getindex_internal(r.ptr, i-1, r.minimal )
    if ptr.cpp_object != C_NULL
       ptr = libSingular.id_Copy(ptr, R.ptr)
    end
@@ -40,13 +40,13 @@ end
 > length of a resolution. Over a field, this should be at most the number of variables
 > in the polynomial ring.
 """
-length(r::sresolution) = r.len - 1
+length(r::sresolution) = libSingular.get_sySize(r.ptr)
 
 function deepcopy_internal(r::sresolution, dict::IdDict)
    R = base_ring(r)
-   ptr = libSingular.res_Copy(r.ptr, Cint(r.len), R.ptr)
+   ptr = libSingular.res_Copy(r.ptr, R.ptr)
    S = parent(r)
-   return S(ptr, r.len)
+   return S(ptr)
 end
 
 ###############################################################################
@@ -62,7 +62,12 @@ end
 > output of this command is useful only in the graded case.
 """
 function betti(r::sresolution)
-   array = libSingular.syBetti(r.ptr, Cint(r.len), r.base_ring.ptr)
+   if r.minimal
+        ideal_list = libSingular.get_minimal_res(r.ptr)
+   else
+        ideal_list = libSingular.get_full_res(r.ptr)
+   end 
+   array = libSingular.syBetti_internal(ideal_list, length(r), r.base_ring.ptr)
    return unsafe_wrap(Array, array[1], array[2:3]; own=true)
 end
 
@@ -83,8 +88,8 @@ function minres(r::sresolution{T}) where T <: AbstractAlgebra.RingElem
       return r
    end
    R = base_ring(r)
-   ptr = libSingular.syMinimize(r.ptr, Cint(r.len), R.ptr)
-   return sresolution{T}(R, r.len, ptr, true)
+   ptr = libSingular.syMinimize(r.ptr, R.ptr)
+   return sresolution{T}(R, ptr, true)
 end
 
 ###############################################################################
@@ -100,13 +105,16 @@ end
 
 function show(io::IO, r::sresolution)
    println(io, "Singular Resolution:")
-   if r.len > 0
-      ptr = libSingular.getindex(r.ptr, Cint(0))
-      print(io, "R^", libSingular.rank(ptr))
+   len = libSingular.get_sySize(r.ptr)
+   if len > 0
+      ptr = libSingular.getindex_internal(r.ptr,0,r.minimal)
+      if ptr.cpp_object != C_NULL
+         print(io, "R^", libSingular.rank(ptr))
+      end
    end
-   for i = 1:r.len - 1
-      ptr = libSingular.getindex(r.ptr, Cint(i-1))
-      if ptr == C_NULL
+   for i = 1:len - 1
+      ptr = libSingular.getindex_internal(r.ptr,i-1,r.minimal)
+      if ptr.cpp_object == C_NULL
          break
       end
       print(io, " <- R^", libSingular.ngens(ptr))
@@ -119,9 +127,13 @@ end
 #
 ###############################################################################
 
-function (S::ResolutionSet{T})(ptr::Ptr{Nothing}, len::Int) where T <: AbstractAlgebra.RingElem
+function (S::ResolutionSet{T})(ptr::libSingular.syStrategy, len::Int = 0) where T <: AbstractAlgebra.RingElem
    R = base_ring(S)
-   return sresolution{T}(R, len, ptr)
+   return sresolution{T}(R, ptr)
+end
+
+function (R::PolyRing{T})(ptr::libSingular.syStrategy, ::Val{:resolution}) where T <: AbstractAlgebra.RingElement
+    return sresolution{T}(R, ptr, libSingular.get_minimal_res(ptr) != C_NULL )
 end
 
 ###############################################################################
@@ -143,7 +155,7 @@ function Resolution(C::Array{smodule{T}, 1}) where T <: AbstractAlgebra.RingElem
     R = base_ring(C[1])
     CC = (m -> m.ptr).(C)
     C_ptr = reinterpret(Ptr{Nothing}, pointer(CC))
-    ptr = libSingular.res_Copy(C_ptr, Cint(len), R.ptr)
-    return sresolution{T}(R, len, ptr)
+    ptr = libSingular.create_SyStrategy(C_ptr, len, R.ptr)
+    return sresolution{T}(R, ptr)
 end
 
diff --git a/test/caller-test.jl b/test/caller-test.jl
new file mode 100644
index 000000000..752d72b3a
--- /dev/null
+++ b/test/caller-test.jl
@@ -0,0 +1,46 @@
+function test_caller()
+    print("caller...")
+
+    R, (x, y) = PolynomialRing(Singular.ZZ, ["x", "y"])
+    @test Singular.LibSets.isEqualInt(R, Singular.ZZ(1), Singular.ZZ(1)) == 1
+
+    R, (x, y) = PolynomialRing(Singular.QQ, ["x", "y"])
+
+    # Input tests
+    @test 1 == Singular.LibSets.isEqualInt(R, 1, 1)
+    @test 1 == Singular.LibSets.isEqualInt(R, x, x)
+    @test 1 == Singular.LibSets.isEqualInt(R, "aa", "aa")
+    @test 1 == Singular.LibSets.isEqualInt(R, Singular.QQ(1), Singular.QQ(1))
+    @test 1 == Singular.LibSets.isEqualInt(R, [1,2,3], [1,2,3])
+    @test 1 == Singular.LibSets.isEqualInt(R, [1 2; 3 4], [1 2; 3 4])
+
+    R, (x,y,z) = PolynomialRing(Singular.QQ, ["x", "y", "z"])
+    
+    i1 = Singular.LibPoly.cyclic(R, 3)
+    i2 = Ideal( R, x+y+z, x*y+x*z+y*z, x*y*z-1 )
+    @test equal(i1, i2)
+
+    vec = FreeModule(R,2)([x,y])
+    mod = Singular.Module(R, vec)
+    i1 = Singular.LibPoly.mod2id(R,mod,[1,2])
+    i2 = Ideal(R, x^2, x*y, y^2, x^2 )
+    @test equal(i1, i2)
+
+    i1 = Ideal(R, x, y)
+    i2 = Ideal(R, x^2, x*y, y^2, x, y)
+    mod = Singular.LibPoly.id2mod(R, i1, [1,2])
+    i1 = Singular.LibPoly.mod2id(R, mod, [1,2])
+    @test equal(i1,i2)
+    @test Singular.LibPoly.content(R,vec) == 1
+    @test Singular.LibPoly.lcm(R,x) == x
+
+    i1 = Ideal(R, x*z, y*z, x^3-y^3)
+    @test Singular.LibStandard.res(R,i1,0) isa Singular.sresolution
+    i1 = Ideal(R, x*z, y*z, x^3-y^3)
+    @test Singular.LibPrimdec.primdecGTZ(R,i1) isa Array
+
+    i1 = Ideal(R, x*z, y*z, x^3-y^3)
+    @test Singular.LibNormal.normal(i1, "withDelta", "prim") isa Array
+
+    println("PASS")
+end
diff --git a/test/runtests.jl b/test/runtests.jl
index 7d7e40063..dc5d3b3ec 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -16,14 +16,17 @@ include("../test/matrix-test.jl")
 include("../test/resolution-test.jl")
 include("../test/module-test.jl")
 include("../test/call_interpreter-test.jl")
+include("../test/caller-test.jl")
 # include("../test/libsingular-test.jl")
 
-test_number()
-test_poly()
-test_ideal()
-test_matrix()
-test_resolution()
-test_module()
-test_call_interpreter()
-# test_libsingular()
-
+@testset "Singular" begin
+    test_caller()
+    test_number()
+    test_poly()
+    test_ideal()
+    test_matrix()
+    test_resolution()
+    test_module()
+    test_call_interpreter()
+    # test_libsingular()
+end