[pygccxml-commit] SF.net SVN: pygccxml:[1475] pyplusplus_dev/pyplusplus
Brought to you by:
mbaas,
roman_yakovenko
|
From: <rom...@us...> - 2008-12-17 22:22:09
|
Revision: 1475
http://pygccxml.svn.sourceforge.net/pygccxml/?rev=1475&view=rev
Author: roman_yakovenko
Date: 2008-12-17 21:43:57 +0000 (Wed, 17 Dec 2008)
Log Message:
-----------
adding ctypes-cpp tester
Added Paths:
-----------
pyplusplus_dev/pyplusplus/cpptypes/
pyplusplus_dev/pyplusplus/cpptypes/decorators.py
pyplusplus_dev/pyplusplus/cpptypes/decorators.pyc
pyplusplus_dev/pyplusplus/cpptypes/get_exports.py
pyplusplus_dev/pyplusplus/cpptypes/mydll/
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.sln
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.suo
pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.vcproj
pyplusplus_dev/pyplusplus/cpptypes/mydll/release/
pyplusplus_dev/pyplusplus/cpptypes/mydll/release/mydll.dll
pyplusplus_dev/pyplusplus/cpptypes/tester.py
Added: pyplusplus_dev/pyplusplus/cpptypes/decorators.py
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/decorators.py (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/decorators.py 2008-12-17 21:43:57 UTC (rev 1475)
@@ -0,0 +1,9 @@
+class public( object ):
+ def __init__(self , dll, decorated_name, return_type, argumen_types):
+ self.decorated_name = decorated_name
+ self.func = getattr( dll, decorated_name )
+ self.func.restype = return_type
+ self.func.argtypes = argumen_types
+
+ def __call__(self, *args, **keywd ):
+ return self.func( *args, **keywd )
Added: pyplusplus_dev/pyplusplus/cpptypes/decorators.pyc
===================================================================
(Binary files differ)
Property changes on: pyplusplus_dev/pyplusplus/cpptypes/decorators.pyc
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: pyplusplus_dev/pyplusplus/cpptypes/get_exports.py
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/get_exports.py (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/get_exports.py 2008-12-17 21:43:57 UTC (rev 1475)
@@ -0,0 +1,289 @@
+# This code was contributed by 'leppton', see
+# https://sourceforge.net/tracker/?func=detail&atid=305470&aid=1559219&group_id=5470
+#
+# This example shows how to use ctypes module to read all
+# function names from dll export directory
+
+import os
+if os.name != "nt":
+ raise Exception("Wrong OS")
+
+import ctypes as ctypes
+import ctypes.wintypes as wintypes
+
+def convert_cdef_to_pydef(line):
+ """\
+convert_cdef_to_pydef(line_from_c_header_file) -> python_tuple_string
+'DWORD var_name[LENGTH];' -> '("var_name", DWORD*LENGTH)'
+
+doesn't work for all valid c/c++ declarations"""
+ l = line[:line.find(';')].split()
+ if len(l) != 2:
+ return None
+ type_ = l[0]
+ name = l[1]
+ i = name.find('[')
+ if i != -1:
+ name, brac = name[:i], name[i:][1:-1]
+ return '("%s", %s*%s)'%(name,type_,brac)
+ else:
+ return '("%s", %s)'%(name,type_)
+
+def convert_cdef_to_structure(cdef, name, data_dict=ctypes.__dict__):
+ """\
+convert_cdef_to_structure(struct_definition_from_c_header_file)
+ -> python class derived from ctypes.Structure
+
+limited support for c/c++ syntax"""
+ py_str = '[\n'
+ for line in cdef.split('\n'):
+ field = convert_cdef_to_pydef(line)
+ if field != None:
+ py_str += ' '*4 + field + ',\n'
+ py_str += ']\n'
+
+ pyarr = eval(py_str, data_dict)
+ class ret_val(ctypes.Structure):
+ _fields_ = pyarr
+ ret_val.__name__ = name
+ ret_val.__module__ = None
+ return ret_val
+
+#struct definitions we need to read dll file export table
+winnt = (
+ ('IMAGE_DOS_HEADER', """\
+ WORD e_magic;
+ WORD e_cblp;
+ WORD e_cp;
+ WORD e_crlc;
+ WORD e_cparhdr;
+ WORD e_minalloc;
+ WORD e_maxalloc;
+ WORD e_ss;
+ WORD e_sp;
+ WORD e_csum;
+ WORD e_ip;
+ WORD e_cs;
+ WORD e_lfarlc;
+ WORD e_ovno;
+ WORD e_res[4];
+ WORD e_oemid;
+ WORD e_oeminfo;
+ WORD e_res2[10];
+ LONG e_lfanew;
+"""),
+
+ ('IMAGE_FILE_HEADER', """\
+ WORD Machine;
+ WORD NumberOfSections;
+ DWORD TimeDateStamp;
+ DWORD PointerToSymbolTable;
+ DWORD NumberOfSymbols;
+ WORD SizeOfOptionalHeader;
+ WORD Characteristics;
+"""),
+
+ ('IMAGE_DATA_DIRECTORY', """\
+ DWORD VirtualAddress;
+ DWORD Size;
+"""),
+
+ ('IMAGE_OPTIONAL_HEADER32', """\
+ WORD Magic;
+ BYTE MajorLinkerVersion;
+ BYTE MinorLinkerVersion;
+ DWORD SizeOfCode;
+ DWORD SizeOfInitializedData;
+ DWORD SizeOfUninitializedData;
+ DWORD AddressOfEntryPoint;
+ DWORD BaseOfCode;
+ DWORD BaseOfData;
+ DWORD ImageBase;
+ DWORD SectionAlignment;
+ DWORD FileAlignment;
+ WORD MajorOperatingSystemVersion;
+ WORD MinorOperatingSystemVersion;
+ WORD MajorImageVersion;
+ WORD MinorImageVersion;
+ WORD MajorSubsystemVersion;
+ WORD MinorSubsystemVersion;
+ DWORD Win32VersionValue;
+ DWORD SizeOfImage;
+ DWORD SizeOfHeaders;
+ DWORD CheckSum;
+ WORD Subsystem;
+ WORD DllCharacteristics;
+ DWORD SizeOfStackReserve;
+ DWORD SizeOfStackCommit;
+ DWORD SizeOfHeapReserve;
+ DWORD SizeOfHeapCommit;
+ DWORD LoaderFlags;
+ DWORD NumberOfRvaAndSizes;
+ IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+""",
+ {'IMAGE_NUMBEROF_DIRECTORY_ENTRIES':16}),
+
+ ('IMAGE_NT_HEADERS', """\
+ DWORD Signature;
+ IMAGE_FILE_HEADER FileHeader;
+ IMAGE_OPTIONAL_HEADER32 OptionalHeader;
+"""),
+
+ ('IMAGE_EXPORT_DIRECTORY', """\
+ DWORD Characteristics;
+ DWORD TimeDateStamp;
+ WORD MajorVersion;
+ WORD MinorVersion;
+ DWORD Name;
+ DWORD Base;
+ DWORD NumberOfFunctions;
+ DWORD NumberOfNames;
+ DWORD AddressOfFunctions;
+ DWORD AddressOfNames;
+ DWORD AddressOfNameOrdinals;
+"""),
+ )
+
+#Construct python ctypes.Structures from above definitions
+data_dict = dict(wintypes.__dict__)
+for definition in winnt:
+ name = definition[0]
+ def_str = definition[1]
+ if len(definition) == 3:
+ data_dict.update(definition[2])
+ type_ = convert_cdef_to_structure(def_str, name, data_dict)
+ data_dict[name] = type_
+ globals()[name] = type_
+
+ ptype = ctypes.POINTER(type_)
+ pname = 'P'+name
+ data_dict[pname] = ptype
+ globals()[pname] = ptype
+
+del data_dict
+del winnt
+
+class DllException(Exception):
+ pass
+
+def read_export_table(dll_name, mmap=False, use_kernel=False):
+ """\
+read_export_table(dll_name [,mmap=False [,use_kernel=False]]])
+ -> list of exported names
+
+default is to load dll into memory: dll sections are aligned to
+page boundaries, dll entry points is called, etc...
+
+with mmap=True dll file image is mapped to memory, Relative Virtual
+Addresses (RVAs) must be mapped to real addresses manually
+
+with use_kernel=True direct kernel32.dll calls are used,
+instead of python mmap module
+
+see http://www.windowsitlibrary.com/Content/356/11/1.html
+for details on Portable Executable (PE) file format
+"""
+ if not mmap:
+ dll = ctypes.cdll.LoadLibrary(dll_name)
+ if dll == None:
+ raise DllException("Cant load dll")
+ base_addr = dll._handle
+
+ else:
+ if not use_kernel:
+ fileH = open(dll_name)
+ if fileH == None:
+ raise DllException("Cant load dll")
+ import mmap
+ m = mmap.mmap(fileH.fileno(), 0, None, mmap.ACCESS_READ)
+ # id(m)+8 sucks, is there better way?
+ base_addr = ctypes.cast(id(m)+8, ctypes.POINTER(ctypes.c_int))[0]
+ else:
+ kernel32 = ctypes.windll.kernel32
+ if kernel32 == None:
+ raise DllException("cant load kernel")
+ fileH = kernel32.CreateFileA(dll_name, 0x00120089, 1,0,3,0,0)
+ if fileH == 0:
+ raise DllException("Cant open, errcode = %d"%kernel32.GetLastError())
+ mapH = kernel32.CreateFileMappingW(fileH,0,0x8000002,0,0,0)
+ if mapH == 0:
+ raise DllException("Cant mmap, errocode = %d"%kernel32.GetLastError())
+ base_addr = ctypes.windll.kernel32.MapViewOfFile(mapH, 0x4, 0, 0, 0)
+ if base_addr == 0:
+ raise DllException("Cant mmap(2), errocode = %d"%kernel32.GetLastError())
+
+ dbghelp = ctypes.windll.dbghelp
+ if dbghelp == None:
+ raise DllException("dbghelp.dll not installed")
+ pimage_nt_header = dbghelp.ImageNtHeader(base_addr)
+ if pimage_nt_header == 0:
+ raise DllException("Cant find IMAGE_NT_HEADER")
+
+ #Functions like dbghelp.ImageNtHeader above have no type information
+ #let's make one prototype for extra buzz
+ #PVOID ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders, PVOID Base,
+ # ULONG Rva, PIMAGE_SECTION_HEADER* LastRvaSection)
+ # we use integers instead of pointers, coz integers are better
+ # for pointer arithmetic
+ prototype = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_int,
+ ctypes.c_int, ctypes.c_int, ctypes.c_int)
+ paramflags = ((1,"NtHeaders",pimage_nt_header),(1,"Base",base_addr),(1,"Rva"),(1,"LastRvaSection",0))
+ ImageRvaToVa = prototype(('ImageRvaToVa', dbghelp), paramflags)
+
+ def cast_rva(rva, type_):
+ va = base_addr + rva
+ if mmap and va > pimage_nt_header:
+ va = ImageRvaToVa(Rva=rva)
+ if va == 0:
+ raise DllException("ImageRvaToVa failed")
+ return ctypes.cast(va, type_)
+
+ if not mmap:
+ dos_header = cast_rva(0, PIMAGE_DOS_HEADER)[0]
+ if dos_header.e_magic != 0x5A4D:
+ raise DllException("IMAGE_DOS_HEADER.e_magic error")
+ nt_header = cast_rva(dos_header.e_lfanew, PIMAGE_NT_HEADERS)[0]
+ else:
+ nt_header = ctypes.cast(pimage_nt_header, PIMAGE_NT_HEADERS)[0]
+ if nt_header.Signature != 0x00004550:
+ raise DllException("IMAGE_NT_HEADERS.Signature error")
+
+ opt_header = nt_header.OptionalHeader
+ if opt_header.Magic != 0x010b:
+ raise DllException("IMAGE_OPTIONAL_HEADERS32.Magic error")
+
+ ret_val = []
+ exports_dd = opt_header.DataDirectory[0]
+ if opt_header.NumberOfRvaAndSizes > 0 or exports_dd != 0:
+ export_dir = cast_rva(exports_dd.VirtualAddress, PIMAGE_EXPORT_DIRECTORY)[0]
+
+ nNames = export_dir.NumberOfNames
+ if nNames > 0:
+ PNamesType = ctypes.POINTER(ctypes.c_int * nNames)
+ names = cast_rva(export_dir.AddressOfNames, PNamesType)[0]
+ for rva in names:
+ name = cast_rva(rva, ctypes.c_char_p).value
+ ret_val.append(name)
+
+ if mmap:
+ if use_kernel:
+ kernel32.UnmapViewOfFile(base_addr)
+ kernel32.CloseHandle(mapH)
+ kernel32.CloseHandle(fileH)
+ else:
+ m.close()
+ fileH.close()
+ return ret_val
+
+
+if __name__ == '__main__':
+ import sys
+ if len(sys.argv) != 2:
+ print 'usage: %s dll_file_name'%sys.argv[0]
+ sys.exit()
+## names = read_export_table(sys.argv[1], mmap=False, use_kernel=False)
+ names = read_export_table(sys.argv[1], mmap=False, use_kernel=False)
+ for name in names:
+ print name
+
+
Added: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.cpp 2008-12-17 21:43:57 UTC (rev 1475)
@@ -0,0 +1,52 @@
+#include "mydll.h"
+#include "windows.h"
+#include <iostream>
+
+number_t::number_t()
+: m_value(0)
+{
+// std::cout << "{C++} number_t( 0 )" << std::endl;
+}
+
+
+number_t::number_t(int value)
+: m_value(value)
+{
+// std::cout << "{C++} number_t( " << value << " )" << std::endl;
+}
+
+number_t::~number_t() {
+// std::cout << "{C++} ~number_t()" << std::endl;
+}
+void number_t::print_it() const {
+ std::cout << "{C++} value: " << m_value << std::endl;
+}
+
+int number_t::get_value() const{
+ return m_value;
+}
+
+void number_t::set_value(int x){
+ m_value = x;
+}
+
+number_t number_t::clone() const{
+ return number_t(*this);
+}
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
Added: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.h 2008-12-17 21:43:57 UTC (rev 1475)
@@ -0,0 +1,17 @@
+#pragma once
+
+class __declspec(dllexport) number_t{
+public:
+ number_t();
+ explicit number_t(int value);
+ virtual ~number_t();
+ void print_it() const;
+ int get_value() const;
+ void set_value(int x);
+
+ number_t clone() const;
+
+private:
+ int m_value;
+};
+
Added: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.sln
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.sln (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.sln 2008-12-17 21:43:57 UTC (rev 1475)
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mydll", "mydll.vcproj", "{E7A34C45-534F-43A6-AF95-3CA2428619E2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E7A34C45-534F-43A6-AF95-3CA2428619E2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E7A34C45-534F-43A6-AF95-3CA2428619E2}.Debug|Win32.Build.0 = Debug|Win32
+ {E7A34C45-534F-43A6-AF95-3CA2428619E2}.Release|Win32.ActiveCfg = Release|Win32
+ {E7A34C45-534F-43A6-AF95-3CA2428619E2}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
Added: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.suo
===================================================================
(Binary files differ)
Property changes on: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.suo
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.vcproj
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.vcproj (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/mydll/mydll.vcproj 2008-12-17 21:43:57 UTC (rev 1475)
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="mydll"
+ ProjectGUID="{E7A34C45-534F-43A6-AF95-3CA2428619E2}"
+ RootNamespace="mydll"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MYDLL_EXPORTS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="2"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MYDLL_EXPORTS"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <File
+ RelativePath=".\mydll.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\mydll.h"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
Added: pyplusplus_dev/pyplusplus/cpptypes/mydll/release/mydll.dll
===================================================================
(Binary files differ)
Property changes on: pyplusplus_dev/pyplusplus/cpptypes/mydll/release/mydll.dll
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Added: pyplusplus_dev/pyplusplus/cpptypes/tester.py
===================================================================
--- pyplusplus_dev/pyplusplus/cpptypes/tester.py (rev 0)
+++ pyplusplus_dev/pyplusplus/cpptypes/tester.py 2008-12-17 21:43:57 UTC (rev 1475)
@@ -0,0 +1,133 @@
+import ctypes
+import unittest
+import decorators
+
+mydll = ctypes.CPPDLL( './mydll/release/mydll.dll' )
+
+#we should keep somewhere decorated-undecorated name mappings
+#I don't feel like parsing source code is a good strategy
+# - there is no way to create mangled name for a function. In this example, other way is used - binary file is parsed
+# and the functions are mapped to dll entry using "human readable" format.
+# GCCXML reports mangled and demangled names of the function, but it is not a cross platform( compile ) solution.
+# It looks like I will have to cause mspdb package to work ( from where ctypes loads dlls? ctypes.windll.msvcr90 ???
+
+
+tmp = [ ( "number_t::number_t(class number_t const &)", "??0number_t@@QAE@ABV0@@Z" )
+ , ( "number_t::number_t(int)", "??0number_t@@QAE@H@Z" )
+ , ( "number_t::number_t(void)", "??0number_t@@QAE@XZ" )
+ , ( "number_t::~number_t(void)", "??1number_t@@UAE@XZ" )
+ , ( "class number_t & number_t::operator=(class number_t const &)", "??4number_t@@QAEAAV0@ABV0@@Z" )
+ , ( "const number_t::'vftable'", "??_7number_t@@6B@" )
+ , ( "int number_t::get_value(void)", "?get_value@number_t@@QBEHXZ" )
+ , ( "void number_t::print_it(void)", "?print_it@number_t@@QBEXXZ" )
+ , ( "void number_t::set_value(int)", "?set_value@number_t@@QAEXH@Z" ) ]
+
+mydll.name_mapping = {}
+for n1, n2 in tmp:
+ mydll.name_mapping[n1] = n2
+ mydll.name_mapping[n2] = n1
+
+# what is the best way to treat overloaded constructors
+class public( object ):
+ def __init__(self, dll, this, name, restype=None, argtypes=None ):
+ self.this = this #reference to class instance
+ self.name = name
+ self.func = getattr( dll, dll.name_mapping[name] )
+ self.func.restype = restype
+ this_call_arg_types = [ ctypes.POINTER( this._obj.__class__ ) ]
+ if argtypes:
+ this_call_arg_types.extend( argtypes )
+ self.func.argtypes = this_call_arg_types
+
+ def __call__(self, *args, **keywd ):
+ return self.func( self.this, *args, **keywd )
+
+class mem_fun_factory( object ):
+ def __init__( self, dll, this ):
+ self.dll = dll
+ self.this = this
+
+ def __call__( self, *args, **keywd ):
+ return public( self.dll, self.this, *args, **keywd )
+
+class Number(ctypes.Structure):
+ #http://www.phpcompiler.org/articles/virtualinheritance.html,
+ _fields_ = [("vptr", ctypes.POINTER(ctypes.c_void_p)),
+ ("m_value", ctypes.c_int)]
+
+ def __init__(self, x=None):
+ mem_fun = mem_fun_factory( mydll, ctypes.byref( self ) )
+ self.get_value = mem_fun( 'int number_t::get_value(void)', restype=ctypes.c_int )
+ self.set_value = mem_fun( 'void number_t::set_value(int)', argtypes=[ctypes.c_int])
+ self.print_it = mem_fun( 'void number_t::print_it(void)' )
+ self.assign = mem_fun( "class number_t & number_t::operator=(class number_t const &)"
+ , restype=ctypes.POINTER(Number)
+ , argtypes=[ctypes.POINTER(Number)] )
+ #overloading example
+ if None is x:
+ mem_fun( 'number_t::number_t(void)' )()
+ elif isinstance( x, int ):
+ mem_fun( 'number_t::number_t(int)', argtypes=[ctypes.c_int] )( x )
+ elif isinstance( x, Number ):
+ mem_fun( 'number_t::number_t(class number_t const &)', argtypes=[ctypes.POINTER(Number)] )( ctypes.byref( x ) )
+ else:
+ raise RuntimeError( "Wrong argument" )
+
+ def __del__(self):
+ public( mydll, ctypes.byref(self), "number_t::~number_t(void)" )()
+
+class tester_t( unittest.TestCase ):
+ def test_constructors(self):
+ obj1 = Number(32)
+ self.failUnless( obj1.m_value == 32 )
+ obj2 = Number()
+ self.failUnless( obj2.m_value == 0 )
+ obj3 = Number(obj1)
+ self.failUnless( obj3.m_value == obj1.m_value == 32 )
+
+ def test_get_value( self ):
+ obj = Number(99)
+ self.failUnless( 99 == obj.get_value() )
+
+ def test_set_value( self ):
+ obj = Number()
+ obj.set_value( 13 )
+ self.failUnless( 13 == obj.get_value() == obj.m_value )
+
+ def test_assign( self ):
+ obj1 = Number(1)
+ obj2 = Number(2)
+ x = obj1.assign( obj2 )
+ #there are special cases, where ctypes could introduce "optimized" behaviour and not create new python object
+ self.failUnless( x is obj1 )
+ self.failUnless( obj1.m_value == obj2.m_value )
+
+def main():
+ obj = Number(42)
+ print obj.m_value
+ print hex(obj.vptr[0])
+ obj.print_it()
+ print '42 == ', obj.get_value()
+
+if __name__ == "__main__":
+ unittest.main()
+
+#problems:
+#consider generic algorithm for resolving overloaded functions call
+# * function name should be unique
+# * write something very smart and bugy and let the smart people to improve it
+
+
+"""
+TODO:
+
+* I think more testers and "demos", before I write code generator:
+ * a class instance passed\returned by value\reference\pointer\smart pointer
+ * function overloading
+ * how much code, we can put in the helper files. I mean class like "public". Or std::vector - there is no reason, to define\generate this class every time
+ * how we are going to manage relationship between objects:
+ class X{...};
+ class Y{ X x; public: const X& get_x() const { return x;} };
+ I think our solution should be very similar to Boost.Python call policies. It is definitely possible to go without it.
+
+"""
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|