diff --git a/pyste/NEWS b/pyste/NEWS new file mode 100644 index 00000000..19ce6b2e --- /dev/null +++ b/pyste/NEWS @@ -0,0 +1,16 @@ +24 Mar 2003 +Default policy for functions/methods that return const T& is now +return_value_policy(). + +22 Mar 2003 +Exporting virtual methods of the base classes in the derived classes too. + +21 Mar 2003 +Added manual support for boost::shared_ptr and std::auto_ptr (see doc). + +19 Mar 2003 +Added support for int, double, float and long operators acting as expected in +python. + +14 Mar 2003 +Fixed bug: Wrappers for protected and virtual methods were not being generated. diff --git a/pyste/doc/introduction.html b/pyste/doc/introduction.html index ffb50e7e..cb4270da 100644 --- a/pyste/doc/introduction.html +++ b/pyste/doc/introduction.html @@ -57,7 +57,7 @@ this will create a file "hello.cpp" in the directory where th run.

Pyste supports the following features:

- +
diff --git a/pyste/doc/policies.html b/pyste/doc/policies.html index 2869889f..da394865 100644 --- a/pyste/doc/policies.html +++ b/pyste/doc/policies.html @@ -55,10 +55,21 @@ function:

+ +
What if a function or method needs a policy and the user -doesn't set one?

-If a function/method needs a policy and one was not set, Pyste will issue a error. -The user should then go in the interface file and set the policy for it, -otherwise the generated cpp won't compile. +doesn't set one?

If a function/method needs a policy and one was not +set, Pyste will issue a error. The user should then go in the interface file +and set the policy for it, otherwise the generated cpp won't compile. +
+ + +
+ + +Note that, for functions/methods that return const T&, the policy +return_value_policy<copy_const_reference>() wil be used by default, because +that's normally what you want. You can change it to something else if you need +to, thought.
diff --git a/pyste/doc/pyste.txt b/pyste/doc/pyste.txt index 8aa71f15..813b77ef 100644 --- a/pyste/doc/pyste.txt +++ b/pyste/doc/pyste.txt @@ -47,6 +47,7 @@ Pyste supports the following features: * Attributes * Enums (both "free" enums and class enums) * Nested Classes +* Support for [^boost::shared_ptr] and [^std::auto_ptr] [page Running Pyste] @@ -214,10 +215,17 @@ function: [blurb [$theme/note.gif] [*What if a function or method needs a policy and the user -doesn't set one?][br][br] -If a function/method needs a policy and one was not set, Pyste will issue a error. -The user should then go in the interface file and set the policy for it, -otherwise the generated cpp won't compile. +doesn't set one?][br][br] If a function/method needs a policy and one was not +set, Pyste will issue a error. The user should then go in the interface file +and set the policy for it, otherwise the generated cpp won't compile. +] + +[blurb +[$theme/note.gif] +Note that, for functions/methods that return [^const T&], the policy +[^return_value_policy()] wil be used by default, because +that's normally what you want. You can change it to something else if you need +to, thought. ] [page:1 Templates] @@ -281,12 +289,14 @@ Suppose you have this function: std::vector names(); -But you don't want to export a vector, you want this function to return -a python list of strings. Boost.Python has an excellent support for that: +But you don't want to export [^std::vector], you want this function +to return a python list of strings. Boost.Python has an excellent support for +that: list names_wrapper() { list result; + // call original function vector v = names(); // put each string from the vector in the list return result; @@ -297,9 +307,8 @@ a python list of strings. Boost.Python has an excellent support for that: def("names", &names_wrapper); } -Nice heh? -Pyste supports this mechanism too. You declare the [^names_wrapper] function in a -header, like "[^test_wrappers.h]", and in the interface file: +Nice heh? Pyste supports this mechanism too. You declare the [^names_wrapper] +function in a header named "[^test_wrappers.h]" and in the interface file: Include("test_wrappers.h") names = Function("names", "test.h") diff --git a/pyste/doc/wrappers.html b/pyste/doc/wrappers.html index e2e47052..66ce4413 100644 --- a/pyste/doc/wrappers.html +++ b/pyste/doc/wrappers.html @@ -30,13 +30,15 @@ Suppose you have this function:

std::vector<std::string> names();

-But you don't want to export a vector<string>, you want this function to return -a python list of strings. -Boost.Python has an excellent support for that:

+But you don't want to export std::vector<string>, you want this function +to return a python list of strings. +Boost.Python has an excellent support for +that:

     list names_wrapper()
     {
         list result;
+        // call original function
         vector<string> v = names();
         // put each string from the vector in the list
         return result;
@@ -48,9 +50,8 @@ Boost.Python has an excellent support for that:

}

-Nice heh? -Pyste supports this mechanism too. You declare the names_wrapper function in a -header, like "test_wrappers.h", and in the interface file:

+Nice heh? Pyste supports this mechanism too. You declare the names_wrapper +function in a header named "test_wrappers.h" and in the interface file:

     Include("test_wrappers.h")
     names = Function("names", "test.h")
diff --git a/pyste/example/basic.h b/pyste/example/basic.h
index a618c192..93e49d36 100644
--- a/pyste/example/basic.h
+++ b/pyste/example/basic.h
@@ -1,3 +1,5 @@
+#include 
+
 namespace basic {
     
 struct C
@@ -10,6 +12,10 @@ struct C
     int foo(int x=1){
         return x+1;
     }
+
+    const std::string& name() { return _name; }
+    void set_name(const std::string& name) { _name = name; }
+    std::string _name;
 };
 
 int call_f(C& c)
diff --git a/pyste/src/ClassExporter.py b/pyste/src/ClassExporter.py
index 6a2d58d7..1de4bf51 100644
--- a/pyste/src/ClassExporter.py
+++ b/pyste/src/ClassExporter.py
@@ -7,6 +7,7 @@ from CodeUnit import CodeUnit
 from EnumExporter import EnumExporter
 from makeid import makeid
 from copy import deepcopy
+import exporterutils
 
 #==============================================================================
 # ClassExporter
@@ -246,24 +247,6 @@ class ClassExporter(Exporter):
                 code = '%s("%s", &%s)' % (def_, name, fullname)
                 self.Add('inside', code)
 
-
-    printed_policy_warnings = {}
-    
-    def CheckPolicy(self, m):
-        'Warns the user if this method needs a policy'            
-        def IsString(type):
-            return type.const and type.name == 'char' and isinstance(type, PointerType)
-        needs_policy = isinstance(m.result, (ReferenceType, PointerType))
-        if IsString(m.result):
-            needs_policy = False
-        has_policy = self.info[m.name].policy is not None
-        if needs_policy and not has_policy:
-            warning = '---> Error: Method "%s" needs a policy.' % m.FullName()
-            if warning not in self.printed_policy_warnings:
-                print warning
-                print 
-                self.printed_policy_warnings[warning] = 1
-            
     
     def ExportMethods(self):
         'Export all the non-virtual methods of this class'        
@@ -305,24 +288,28 @@ class ClassExporter(Exporter):
         methods = [x for x in self.public_members if IsExportable(x)]        
         
         for method in methods:
-            if self.info[method.name].exclude:
-                continue # skip this method
+            method_info = self.info[method.name]
+            
+            # skip this method if it was excluded by the user
+            if method_info.exclude:
+                continue 
 
-            name = self.info[method.name].rename or method.name
+            # rename the method if the user requested
+            name = method_info.rename or method.name
             
             # warn the user if this method needs a policy and doesn't have one
-            self.CheckPolicy(method)            
+            method_info.policy = exporterutils.HandlePolicy(method, method_info.policy)
             
             # check for policies
-            policy = self.info[method.name].policy or ''
+            policy = method_info.policy or ''
             if policy:
                 policy = ', %s%s()' % (namespaces.python, policy.Code())
             # check for overloads
             overload = ''
             if method.minArgs != method.maxArgs:
                 # add the overloads for this method
-                overload_name = OverloadName(method)
                 DeclareOverloads(method)
+                overload_name = OverloadName(method)
                 overload = ', %s%s()' % (namespaces.pyste, overload_name)
         
             # build the .def string to export the method
@@ -337,7 +324,7 @@ class ClassExporter(Exporter):
                 code = '.staticmethod("%s")' % name
                 self.Add('inside', code)
             # add wrapper code if this method has one
-            wrapper = self.info[method.name].wrapper
+            wrapper = method_info.wrapper
             if wrapper and wrapper.code:
                 self.Add('declaration', wrapper.code)
 
diff --git a/pyste/src/FunctionExporter.py b/pyste/src/FunctionExporter.py
index 60735ca0..e72c1392 100644
--- a/pyste/src/FunctionExporter.py
+++ b/pyste/src/FunctionExporter.py
@@ -2,8 +2,12 @@ from Exporter import Exporter
 from policies import *
 from declarations import *
 from settings import *
+import exporterutils
 
 
+#==============================================================================
+# FunctionExporter
+#==============================================================================
 class FunctionExporter(Exporter):
     'Generates boost.python code to export the given function.'
     
@@ -14,7 +18,7 @@ class FunctionExporter(Exporter):
     def Export(self, codeunit, exported_names):
         decls = self.GetDeclarations(self.info.name)
         for decl in decls:
-            self.CheckPolicy(decl)
+            self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy)
             self.ExportDeclaration(decl, len(decls) == 1, codeunit)
         self.GenerateOverloads(decls, codeunit)            
 
@@ -23,17 +27,6 @@ class FunctionExporter(Exporter):
         return self.info.name
 
 
-    def CheckPolicy(self, func):
-        'Warns the user if this function needs a policy'            
-        def IsString(type):
-            return type.const and type.name == 'char' and isinstance(type, PointerType)    
-        needs_policy = isinstance(func.result, (ReferenceType, PointerType))
-        if IsString(func.result):
-            needs_policy = False
-        if needs_policy and self.info.policy is None:
-            print '---> Error: Function "%s" needs a policy.' % func.FullName() 
-            print 
-
     def ExportDeclaration(self, decl, unique, codeunit):
         name = self.info.rename or decl.name
         defs = namespaces.python + 'def("%s", ' % name
diff --git a/pyste/src/exporterutils.py b/pyste/src/exporterutils.py
index 5134a1e5..d7ded496 100644
--- a/pyste/src/exporterutils.py
+++ b/pyste/src/exporterutils.py
@@ -3,6 +3,8 @@ Various helpers for interface files.
 '''
 
 from settings import *
+from policies import *
+from declarations import *
 
 #==============================================================================
 # FunctionWrapper
@@ -24,3 +26,39 @@ class FunctionWrapper(object):
             return namespaces.pyste + self.name
         else:
             return self.name
+
+
+#==============================================================================
+# HandlePolicy
+#==============================================================================
+def HandlePolicy(function, policy):
+    '''Show a warning to the user if the function needs a policy and doesn't
+    have one. Return a policy to the function, which is the given policy itself
+    if it is not None, or a default policy for this method.
+    '''
+    
+    def IsString(type):
+        'Return True if the Type instance can be considered a string'
+        return type.const and type.name == 'char' and isinstance(type, PointerType)
+    
+    result = function.result
+    # basic test if the result type demands a policy
+    needs_policy = isinstance(result, (ReferenceType, PointerType))
+    # if the function returns const char*, a policy is not needed
+    if IsString(result):
+        needs_policy = False
+    # if returns a const T&, set the default policy
+    if policy is None and result.const and isinstance(result, ReferenceType):
+        policy = return_value_policy(copy_const_reference)
+    # show a warning to the user, if needed
+    if needs_policy and policy is None:
+        global _printed_warnings
+        warning = '---> Error: Method "%s" needs a policy.' % m.FullName()
+        if warning not in _printed_warnings:
+            print warning
+            print 
+            # avoid double prints of the same warning
+            _printed_warnings[warning] = 1
+    return policy
+            
+_printed_warnings = {} # used to avoid double-prints in HandlePolicy
diff --git a/pyste/src/pyste.py b/pyste/src/pyste.py
index 34afdecd..28f3d497 100644
--- a/pyste/src/pyste.py
+++ b/pyste/src/pyste.py
@@ -25,13 +25,8 @@ import exporterutils
 import settings
 from policies import *
 from CppParser import CppParser, CppParserError
-from Exporter import Exporter
-from FunctionExporter import FunctionExporter
-from ClassExporter import ClassExporter
-from IncludeExporter import IncludeExporter
-from HeaderExporter import HeaderExporter
 
-__VERSION__ = '0.5.9'
+__VERSION__ = '0.6'
 
 def GetDefaultIncludes():
     if 'INCLUDE' in os.environ: