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.
|-- include | |-- Hello.h | `-- IHello.h |-- src | |-- Hello.cpp | `-- Main.cpp `-- wscript
IHello.h
#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_ */
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.
Hello.h
#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
#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
#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;
}
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#.
wscript
#!/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')
Let's build it now.
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
#ifndef HELLO_H_
#define HELLO_H_
class Hello {
public:
void sayHello();
};
#endif /* HELLO_H_ */
Hello.cpp
#include <iostream>
#include "Hello.h"
using namespace std;
void Hello::sayHello() {
cout << "Hello World" << endl;
}
Main.cpp
#include "Hello.h"
using namespace std;
int main() {
Hello h;
h.sayHello();
return 0;
}
wscript
#!/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)
#!/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
#!/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
#!/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.
#!/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.
#!/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:
Comments (Atom)