set tabstop=4 set shiftwidth=4 set expandtab set autoindent set smartindent set number set ruler set hlsearch set ignorecase
Tuesday, July 31, 2012
My .vimrc
Monday, July 30, 2012
How to Dynamically Load C++ Shared Libraries on Linux
Below is an example how to dynamically load a C++ shared library on Linux.
This is the project structure.
First, we need to create C-like functions for creating an instance of Hello and destroying it. This is a kind of factory class. Second, we need to add extern "C" to avoid C++ name mangling.
As you can see in the Main.cpp, we only include IHello.h and not Hello.h (the implementation), which is a pure virtual class. This is something like an interface in Java/C#.
Let's build it now.
|-- include | |-- Hello.h | `-- IHello.h |-- src | |-- Hello.cpp | `-- Main.cpp `-- wscript
IHello.h
1 2 3 4 5 6 7 8 9 10 11 12 13 | #ifndef IHELLO_H_ #define IHELLO_H_ class IHello { public : virtual void SayHello() const = 0; virtual ~IHello() {}; }; typedef IHello* (*CreateFunc)(); typedef void (*DestroyFunc)(IHello*); #endif /* IHELLO_H_ */ |
Hello.h
1 2 3 4 5 6 7 8 9 10 11 12 13 | #ifndef HELLO_H_ #define HELLO_H_ #include "IHello.h" class Hello : public IHello { public : Hello(); void SayHello() const ; virtual ~Hello(); }; #endif /* HELLO_H_ */ |
Hello.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include <iostream> #include "Hello.h" using namespace std; Hello::Hello() { cout << "Creating Hello" << endl; } Hello::~Hello() { cout << "Destroying Hello" << endl; } void Hello::SayHello() const { cout << "Hello World" << endl; } extern "C" IHello* CreateHello() { return new Hello; } extern "C" void DestroyHello(IHello* h) { delete h; } |
Main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #include <iostream> #include <dlfcn.h> #include "IHello.h" using namespace std; int main() { void * helloLib = dlopen( "./libhello.so" , RTLD_LAZY); if (!helloLib) { cerr << "Error loading libhello.so" << endl; return 1; } CreateFunc cf = (CreateFunc) dlsym(helloLib, "CreateHello" ); IHello* hello = cf(); hello->SayHello(); DestroyFunc df = (DestroyFunc) dlsym(helloLib, "DestroyHello" ); (df)(hello); if (dlclose(helloLib)) { cerr << "Error closing libhello.so" << endl; return 1; } return 0; } |
wscript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | #!/usr/bin/env python top = '.' out = 'build' def options(opt): opt.load( 'compiler_cxx' ) def configure(ctx): ctx.load( 'compiler_cxx' ) def build(ctx): ctx.shlib(source = 'src/Hello.cpp' , cxxflags = [ '-g' , '-Wall' ], target = 'hello' , includes = [ 'include' ]) ctx.program(source = 'src/Main.cpp' , cxxflags = [ '-g' , '-Wall' ], lib = [ 'dl' ], includes = [ 'include' ], target = 'main' ) |
waf configure build cd build ./mainBelow is the output.
Creating Hello Hello World Destroying Hello
Sunday, July 22, 2012
Getting Started with Waf to Build C/C++ Applications
Waf is another build tool like SCons. It's a fork of SCons that is more Pythonic than SCons. Here is a simple example how to get build a C++ application with Waf.
waf-project ├── include │ └── Hello.h ├── src │ ├── Hello.cpp │ └── Main.cpp └── wscript
Hello.h
1 2 3 4 5 6 7 8 9 10 | #ifndef HELLO_H_ #define HELLO_H_ class Hello { public : void sayHello(); }; #endif /* HELLO_H_ */ |
Hello.cpp
1 2 3 4 5 6 7 | #include <iostream> #include "Hello.h" using namespace std; void Hello::sayHello() { cout << "Hello World" << endl; } |
Main.cpp
1 2 3 4 5 6 7 8 9 | #include "Hello.h" using namespace std; int main() { Hello h; h.sayHello(); return 0; } |
wscript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #!/usr/bin/env python APPNAME = 'waf-project' VERSION = '0.1' top = '.' out = 'build' def options(ctx): ctx.load( 'compiler_cxx' ) ctx.add_option( "--shared" , action = "store_true" , help = "build shared library" ) ctx.add_option( "--static" , action = "store_true" , help = "build static library" ) def configure(ctx): ctx.load( 'compiler_cxx' ) def build(ctx): if ctx.options.shared: ctx.shlib(source = "src/Hello.cpp" , target = "hello" , includes = [ "include" ], cxxflags = "-g -Wall -O0" ) elif ctx.options.static: ctx.stlib(source = "src/Hello.cpp" , target = "hello" , includes = [ "include" ], cxxflags = "-g -Wall -O0" ) else : # by default, build a shared library ctx.shlib(source = "src/Hello.cpp" , target = "hello" , includes = [ "include" ], cxxflags = "-g -Wall -O0" ) ctx.program(source = "src/Main.cpp" , target = "main" , includes = [ "include" ], use = "hello" ) |
waf configureThis will create all the configuration files in a "build" directory as specified in the out variable.
waf configure build --staticThis will create a "hello" static library and a "main" program that is statically linked with the "hello" static library. The static library and the program will be created in a "build" directory as specified in the "out" variable.
waf configure build --sharedThis will create a "hello" shared library and a "main" program that is dynamically linked with the "hello" shared library. The shared library and the program will be created in a "build" directory as specified in the "out" variable.
Friday, July 13, 2012
Compressing Characters in Python
This is an in-place algorithm for compressing characters, e.g.
AABBCCCDDXYYZ --> A2B2C3D2XY2ZThe reason why the output isn't A2B2C3D2X1Y2Z1 is because adding 1 for only any non-repeated contagious character can make the compressed data bigger than the actual data, e.g.
ABCD --> A1B1C1D1 (A1B1C1D1 is larger than ABCD)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #!/usr/bin/env python def compress(l): if len (l) = = 0 : return [] counter = 1 tmp = l[ 0 ] i = 1 while i < len (l): if l[i] ! = tmp: new_index = update(i, counter, l) i = new_index + 1 tmp = l[i] counter = 1 else : counter + = 1 i + = 1 update(i, counter, l) return l def update(current_index, counter, l): if counter = = 1 : return current_index - 1 new_index = current_index - (counter - 1 ) l[new_index] = str (counter) shift(current_index, new_index + 1 , l) return new_index def shift(source_index, destination_index, l): last_index = len (l) i = 0 while (source_index + i) < last_index: l[destination_index + i] = l[source_index + i] i + = 1 last_index = destination_index + i del l[last_index:] if __name__ = = "__main__" : assert ([ 'A' , '4' , 'B' , '2' , 'C' , 'D' , '3' , 'E' , '2' , 'A' , '2' , 'X' , 'Y' , '5' , 'Z' ] = = compress([ "A" , "A" , "A" , "A" , "B" , "B" , "C" , "D" , "D" , "D" , "E" , "E" , "A" , "A" , "X" , "Y" , "Y" , "Y" , "Y" , "Y" , "Z" ])) |
Converting Relative Path to Absolute Path in Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/env python def get_absolute_path(path): files = path.split( "/" ) l = [] for f in files: if f = = ".." : l.pop() else : l.append(f) return "/" .join(l) if __name__ = = "__main__" : assert "/windows/temp/" = = get_absolute_path( "/windows/abs/../temp/new/../" ) assert "windows/temp/" = = get_absolute_path( "windows/abs/../temp/new/../" ) assert "/windows/temp" = = get_absolute_path( "/windows/abs/../temp/new/.." ) |
Wednesday, July 11, 2012
Implementing Word Completion in Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #!/usr/bin/env python class Node( object ): def __init__( self , value = None ): self .value = value self .children = [] class Trie( object ): def __init__( self ): self .root = Node( "Root" ) def add( self , key): self ._add( self .root, key, 0 ) def _add( self , node, key, index): if len (key) = = index: return next_node = None for n in node.children: if n.value = = key[index]: next_node = n break if next_node is None : next_node = Node(key[index]) node.children.append(next_node) print "Adding" , next_node.value, "into" , node.value self ._add(next_node, key, index + 1 ) def find( self , key): return self ._find( self .root, key, 0 ) def _find( self , node, key, index): if len (key) = = index: return node found = False for n in node.children: if n.value = = key[index]: found = True last_found_node = self ._find(n, key, index + 1 ) if not found: return None else : return last_found_node def search( self , key): result = [] last_node = self .find(key) if last_node is None : return result self ._search(last_node, key, "", result) for i in xrange ( 0 , len (result)): result[i] = key + result[i] return result def _search( self , node, key, char, result): if len (node.children) = = 0 : result.append(char) return for n in node.children: self ._search(n, key, char + n.value, result) class WordCompletion( object ): def __init__( self , words): self .trie = Trie() for word in words: print "===== Inserting" , word, "=====" self .trie.add(word) def search( self , prefix): return self .trie.search(prefix) if __name__ = = "__main__" : words = [ "ABCD" , "ABCE" , "AFG" , "AFHIJ" , "AFHIK" , "XY" ] wc = WordCompletion(words) assert [ 'ABCD' , 'ABCE' , 'AFG' , 'AFHIJ' , 'AFHIK' ] = = wc.search( "A" ) assert [ 'AFHIJ' , "AFHIK" ] = = wc.search( "AFHI" ) assert [ 'AFHIJ' , 'AFHIK' ] = = wc.search( "AFH" ) assert [ 'ABCD' , 'ABCE' ] = = wc.search( "ABC" ) assert [] = = wc.search( "whatever" ) |
Wednesday, July 4, 2012
Implementing Tic-Tac-Toe in Python
This is my simple tic-tac-toe implementation in Python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #!/usr/bin/env python class TicTacToe( object ): def __init__( self , n = 3 ): self .n = n self .board = [] for i in xrange ( self .n): self .board.append([]) for j in xrange ( self .n): self .board[i].append( " " ) def draw( self ): for x in self .board: print x def move( self , player, x, y): if x > = self .n or y > = self .n: raise Exception( "Invalid move!" ) if self .board[x][y] ! = " " : raise Exception( "Invalid move!" ) self .board[x][y] = player def win( self , player): same = True for i in xrange ( self .n): if self .board[ 0 ][i] ! = player: same = False break if same: return True same = True for i in xrange ( self .n): if self .board[i][ 0 ] ! = player: same = False break if same: return True same = True for i in xrange ( self .n): if self .board[ self .n - 1 ][i] ! = player: same = False break if same: return True same = True for i in xrange ( self .n): if self .board[i][ self .n - 1 ] ! = player: same = False break if same: return True same = True for i in xrange ( self .n): if self .board[i][i] ! = player: same = False break if same: return True same = True x = - 1 y = self .n for i in xrange ( self .n): x + = 1 y - = 1 if self .board[x][y] ! = player: same = False break if same: return True return False if __name__ = = "__main__" : player1 = "X" player2 = "O" t3 = TicTacToe() t3.move(player1, 2 , 0 ) t3.move(player2, 1 , 2 ) t3.move(player1, 1 , 1 ) t3.move(player2, 2 , 1 ) t3.move(player1, 0 , 2 ) t3.draw() print "Player1" , "won" if t3.win(player1) else "lost" print "Player2" , "won" if t3.win(player2) else "lost" |
Tuesday, July 3, 2012
How to Generate a List of Possible Words in a Phone Number in Python
Example, if we type 2 -> 2 -> 3. The we have can have words like "AAD", "AAE", "AAF", etc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/usr/bin/env python numbers = { "2" : [ "A" , "B" , "C" ], "3" : [ "D" , "E" , "F" ], "4" : [ "G" , "H" , "I" ], "5" : [ "J" , "K" , "L" ], "6" : [ "M" , "N" , "O" ], "7" : [ "P" , "Q" , "R" ], "8" : [ "S" , "T" , "U" ], "9" : [ "V" , "W" , "X" ], "0" : [ "Y" , "Z" ]} def generate(input_list): return gen(input_list, 0 , "") def gen(input_list, index, n): if index > len (input_list) - 1 : return [n] output_list = [] for i in input_list[index]: index + = 1 for x in numbers[i]: tmp = gen(input_list, index, x) for t in tmp: output_list.append(n + t) return output_list if __name__ = = "__main__" : for i in generate([ "2" , "4" , "3" , "6" ]): print i |
Subscribe to:
Posts (Atom)