[pypy-svn] r75998 - in pypy/branch/reflex-support/pypy/module/cppyy: . include src test

wlav at codespeak.net wlav at codespeak.net
Wed Jul 7 20:04:05 CEST 2010


Author: wlav
Date: Wed Jul  7 20:04:02 2010
New Revision: 75998

Modified:
   pypy/branch/reflex-support/pypy/module/cppyy/capi.py
   pypy/branch/reflex-support/pypy/module/cppyy/converter.py
   pypy/branch/reflex-support/pypy/module/cppyy/executor.py
   pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h
   pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py
   pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx
   pypy/branch/reflex-support/pypy/module/cppyy/test/example01.cxx
   pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py
Log:
Support calls for double and char* on instances.


Modified: pypy/branch/reflex-support/pypy/module/cppyy/capi.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/capi.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/capi.py	Wed Jul  7 20:04:02 2010
@@ -31,20 +31,20 @@
     "callstatic_l",
     [rffi.VOIDP, rffi.INT, rffi.INT, rffi.VOIDPP], rffi.LONG,
     compilation_info=eci)
-c_callstatic_d = rffi.llexternal(
-    "callstatic_d",
-    [rffi.VOIDP, rffi.INT, rffi.INT, rffi.VOIDPP], rffi.DOUBLE,
-    compilation_info=eci)
-c_construct = rffi.llexternal(
-    "construct",
+c_cppyy_construct = rffi.llexternal(
+    "cppyy_construct",
     [rffi.VOIDP, rffi.INT, rffi.VOIDPP], rffi.VOIDP,
     compilation_info=eci)
 c_cppyy_call_l = rffi.llexternal(
     "cppyy_call_l",
     [rffi.VOIDP, rffi.INT, rffi.VOIDP, rffi.INT, rffi.VOIDPP], rffi.LONG,
     compilation_info=eci)
-c_destruct = rffi.llexternal(
-    "destruct",
+c_cppyy_call_d = rffi.llexternal(
+    "cppyy_call_d",
+    [rffi.VOIDP, rffi.INT, rffi.VOIDP, rffi.INT, rffi.VOIDPP], rffi.DOUBLE,
+    compilation_info=eci)
+c_cppyy_destruct = rffi.llexternal(
+    "cppyy_destruct",
     [rffi.VOIDP, rffi.VOIDP], lltype.Void,
     compilation_info=eci)
 

Modified: pypy/branch/reflex-support/pypy/module/cppyy/converter.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/converter.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/converter.py	Wed Jul  7 20:04:02 2010
@@ -12,7 +12,7 @@
 
 class IntConverter(TypeConverter):
     def convert_argument(self, space, w_obj):
-        arg = space.int_w(w_obj)
+        arg = space.c_int_w(w_obj)
         x = lltype.malloc(rffi.LONGP.TO, 1, flavor='raw')
         x[0] = arg
         return rffi.cast(rffi.VOIDP, x)        

Modified: pypy/branch/reflex-support/pypy/module/cppyy/executor.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/executor.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/executor.py	Wed Jul  7 20:04:02 2010
@@ -17,18 +17,12 @@
 
 class DoubleExecutor(FunctionExecutor):
     def execute(self, space, func, cppthis, num_args, args):
-        if cppthis is not None:
-            raise NotImplementedError
-        else:
-            result = capi.c_callstatic_d(func.cpptype.handle, func.method_index, num_args, args)
+        result = capi.c_cppyy_call_d(func.cpptype.handle, func.method_index, cppthis, num_args, args)
         return space.wrap(result)
 
 class CStringExecutor(FunctionExecutor):
     def execute(self, space, func, cppthis, num_args, args):
-        if cppthis is not None:
-            raise NotImplementedError
-        else:
-            lresult = capi.c_cppyy_call_l(func.cpptype.handle, func.method_index, cppthis, num_args, args)
+        lresult = capi.c_cppyy_call_l(func.cpptype.handle, func.method_index, cppthis, num_args, args)
         ccpresult = rffi.cast(rffi.CCHARP, lresult)
         result = capi.charp2str_free(ccpresult)
         return space.wrap(result)

Modified: pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/include/reflexcwrapper.h	Wed Jul  7 20:04:02 2010
@@ -7,10 +7,10 @@
 #endif // ifdef __cplusplus
     void* cppyy_get_typehandle(const char* class_name);
 
-    double callstatic_d(void* handle, int method_index, int numargs, void* args[]);
+    void* cppyy_construct(void* handle, int numargs, void* args[]);
     long cppyy_call_l(void* handle, int method_index, void* self, int numargs, void* args[]);
-    void* construct(void* handle, int numargs, void* args[]);
-    void destruct(void* handle, void* self);
+    double cppyy_call_d(void* handle, int method_index, void* self, int numargs, void* args[]);
+    void cppyy_destruct(void* handle, void* self);
 
     int num_methods(void* handle);
     char* method_name(void* handle, int method_index);

Modified: pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py	Wed Jul  7 20:04:02 2010
@@ -113,7 +113,7 @@
     def call(self, cppthis, args_w):
         assert not cppthis
         args = self.prepare_arguments(args_w)
-        result = capi.c_construct(self.cpptype.handle, len(args_w), args)
+        result = capi.c_cppyy_construct(self.cpptype.handle, len(args_w), args)
         self.free_arguments(args)
         return W_CPPObject(self.cpptype, result)
 
@@ -208,13 +208,19 @@
         self.cppclass = cppclass
         self.rawobject = rawobject
 
+    def _nullcheck(self):
+        if not self.rawobject:
+            raise OperationError(self.space.w_ReferenceError, self.space.wrap("trying to access a NULL pointer"))
+
     def invoke(self, method_name, args_w):
+        self._nullcheck()
         cppclass = jit.hint(self.cppclass, promote=True)
         overload = cppclass.get_overload(method_name)
         return overload.call(self.rawobject, args_w)
 
     def destruct(self):
-        capi.c_destruct(self.cppclass.handle, self.rawobject)
+        capi.c_cppyy_destruct(self.cppclass.handle, self.rawobject)
+        self.rawobject = NULL_VOIDP
 
 W_CPPObject.typedef = TypeDef(
     'CPPObject',

Modified: pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/src/reflexcwrapper.cxx	Wed Jul  7 20:04:02 2010
@@ -8,13 +8,18 @@
    return Reflex::Type::ByName(class_name).Id();
 }
 
-double callstatic_d(void* handle, int method_index, int numargs, void* args[]) {
-    double result;
+
+void* cppyy_construct(void* handle, int numargs, void* args[]) {
     std::vector<void*> arguments(args, args+numargs);
     Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
-    m.Invoke(result, arguments);
-    return result;
+    std::vector<Reflex::Type> argtypes;
+    argtypes.reserve(numargs);
+    for (int i = 0; i < numargs; i++) {
+        argtypes.push_back(Reflex::Type::ByName("int"));
+    }
+    Reflex::Type constructor_type = Reflex::FunctionTypeBuilder(
+            Reflex::Type::ByName("void"), argtypes);
+    return t.Construct(constructor_type, arguments).Address();
 }
 
 long cppyy_call_l(void* handle, int method_index,
@@ -32,20 +37,22 @@
     return result;
 }
 
-void* construct(void* handle, int numargs, void* args[]) {
+double cppyy_call_d(void* handle, int method_index,
+                    void* self, int numargs, void* args[]) {
+    double result;
     std::vector<void*> arguments(args, args+numargs);
     Reflex::Type t((Reflex::TypeName*)handle);
-    std::vector<Reflex::Type> argtypes;
-    argtypes.reserve(numargs);
-    for (int i = 0; i < numargs; i++) {
-    	argtypes.push_back(Reflex::Type::ByName("int"));
+    Reflex::Member m = t.FunctionMemberAt(method_index);
+    if (self) {
+        Reflex::Object o(t, self);
+        m.Invoke(o, result, arguments);
+    } else {
+        m.Invoke(result, arguments);
     }
-    Reflex::Type constructor_type = Reflex::FunctionTypeBuilder(
-	    Reflex::Type::ByName("void"), argtypes);
-    return t.Construct(constructor_type, arguments).Address();
-}
+    return result;
+}   
 
-void destruct(void* handle, void* self) {
+void cppyy_destruct(void* handle, void* self) {
     Reflex::Type t((Reflex::TypeName*)handle);
     t.Destruct(self, true);
 }

Modified: pypy/branch/reflex-support/pypy/module/cppyy/test/example01.cxx
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/test/example01.cxx	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/example01.cxx	Wed Jul  7 20:04:02 2010
@@ -1,4 +1,6 @@
 #include <iostream>
+#include <sstream>
+#include <string>
 #include <stdlib.h>
 #include <string.h>
 
@@ -28,31 +30,53 @@
         count--;
     }
 
-    static int add1(int a) {
+// class methods
+    static int staticAddOneToInt(int a) {
         return a + 1;
     }
-    static int add1(int a, int b) {
+    static int staticAddOneToInt(int a, int b) {
         return a + b + 1;
     }
-    static double adddouble(double a) {
+    static double staticAddToDouble(double a) {
         return a + 0.01;
     }
-    static int atoi(const char* str) {
+    static int staticAtoi(const char* str) {
         return ::atoi(str);
     }
-    static char* strcpy(const char* strin) {
+    static char* staticStrcpy(const char* strin) {
         char* strout = (char*)malloc(::strlen(strin + 1));
         ::strcpy(strout, strin);
         return strout;
     }
 
-    static int getcount() {
+    static int getCount() {
         std::cout << "getcount called" << std::endl;
         return count;
     }
-    int add(int a) {
+
+// instance methods
+    int addDataToInt(int a) {
+        return somedata + a;
+    }
+
+    double addDataToDouble(double a) {
         return somedata + a;
     }
+
+    int addDataToAtoi(const char* str) {
+        return ::atoi(str) + somedata;
+    }   
+
+    char* addToStringValue(const char* str) {
+        int out = ::atoi(str) + somedata;
+        std::ostringstream ss;
+        ss << out << std::ends;
+        std::string result = ss.str();
+        char* cresult = (char*)malloc(result.size()+1);
+        ::strcpy(cresult, result.c_str());
+        return cresult;
+    }
+
 };
 
 int example01::count = 0;

Modified: pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py	(original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py	Wed Jul  7 20:04:02 2010
@@ -1,5 +1,4 @@
-import py
-import os
+import py, os
 from pypy.conftest import gettestobjspace
 from pypy.module.cppyy import interp_cppyy, executor
 
@@ -16,7 +15,7 @@
     def test_class_query(self):
         lib = interp_cppyy.load_lib(space, shared_lib)
         w_cppyyclass = lib.type_byname("example01")
-        adddouble = w_cppyyclass.function_members["adddouble"]
+        adddouble = w_cppyyclass.function_members["staticAddToDouble"]
         func, = adddouble.functions
         assert isinstance(func.executor, executor.DoubleExecutor)
         assert func.arg_types == ["double"]
@@ -30,40 +29,95 @@
             import cppyy
             return cppyy.load_lib(%r)""" % (shared_lib, ))
 
-    def test_example01static(self):
+    def test_example01static_int(self):
+        """Test passing of an int, returning of an int, and overloading on a
+            differening number of arguments."""
+        import sys
         t = self.example01.type_byname("example01")
-        # also tests overloading by number of args
-        res = t.invoke("add1", 1)
+        res = t.invoke("staticAddOneToInt", 1)
         assert res == 2
-        res = t.invoke("add1", 1, 2)
+        res = t.invoke("staticAddOneToInt", 1L)
+        assert res == 2
+        res = t.invoke("staticAddOneToInt", 1, 2)
         assert res == 4
-        raises(TypeError, 't.invoke("add1", 1, [])')
+        res = t.invoke("staticAddOneToInt", -1)
+        assert res == 0
+        res = t.invoke("staticAddOneToInt", sys.maxint-1)
+        assert res == sys.maxint
+        res = t.invoke("staticAddOneToInt", sys.maxint)
+        assert res == -sys.maxint-1
+
+        raises(TypeError, 't.invoke("staticAddOneToInt", 1, [])')
+        raises(TypeError, 't.invoke("staticAddOneToInt", 1.)')
+        raises(OverflowError, 't.invoke("staticAddOneToInt", sys.maxint+1)')
 
 
     def test_example01static_double(self):
+        """Test passing of a double and returning of a double on a static function."""
         t = self.example01.type_byname("example01")
-        res = t.invoke("adddouble", 0.09)
+        res = t.invoke("staticAddToDouble", 0.09)
         assert res == 0.09 + 0.01
 
     def test_example01static_constcharp(self):
+        """Test passing of a C string and returning of a C string on a static
+            function."""
         t = self.example01.type_byname("example01")
-        res = t.invoke("atoi", "1")
+        res = t.invoke("staticAtoi", "1")
         assert res == 1
 
-        res = t.invoke("strcpy", "aap")
+        res = t.invoke("staticStrcpy", "aap")
+        assert res == "aap"
+
+        res = t.invoke("staticStrcpy", u"aap")
         assert res == "aap"
 
-    def test_example01method(self):
+        raises(TypeError, 't.invoke("staticStrcpy", 1.)')
+
+    def test_example01method_int(self):
+        """Test passing of a int, returning of a int, and memory cleanup, on
+            a method."""
         t = self.example01.type_byname("example01")
-        count = t.invoke("getcount")
-        assert count == 0
+        assert t.invoke("getCount") == 0
         instance = t.construct(7)
-        count = t.invoke("getcount")
-        assert count == 1
-        res = instance.invoke("add", 4)
+        assert t.invoke("getCount") == 1
+        res = instance.invoke("addDataToInt", 4)
         assert res == 11
+        res = instance.invoke("addDataToInt", -4)
+        assert res == 3
+        instance.destruct()
+        assert t.invoke("getCount") == 0
+        raises(ReferenceError, 'instance.invoke("addDataToInt", 4)')
+
+        instance = t.construct(7)
+        instance2 = t.construct(8)
+        assert t.invoke("getCount") == 2
         instance.destruct()
-        count = t.invoke("getcount")
-        assert count == 0
+        assert t.invoke("getCount") == 1
+        instance2.destruct()
+        assert t.invoke("getCount") == 0
+
+    def test_example01method_double(self):
+        """Test passing of a double and returning of double on a method"""
+        t = self.example01.type_byname("example01")
+        instance = t.construct(13)
+        res = instance.invoke("addDataToDouble", 16)
+        assert round(res-29, 8) == 0.
+        instance = t.construct(-13)
+        res = instance.invoke("addDataToDouble", 16)
+        assert round(res-3, 8) == 0.
+
+    def test_example01method_constcharp(self):
+        """Test passing of a C string and returning of a C string on a
+            method."""
+
+        t = self.example01.type_byname("example01")
+        instance = t.construct(42)
+
+        res = instance.invoke("addDataToAtoi", "13")
+        assert res == 55
 
+        res = instance.invoke("addToStringValue", "12")
+        assert res == "54"
+        res = instance.invoke("addToStringValue", "-12")
+        assert res == "30"
 



More information about the Pypy-commit mailing list