[Forward][python]How do I pass a variable by reference?

September 20th, 2011 by bettermanlu

http://stackoverflow.com/questions/986006/python-how-do-i-pass-a-variable-by-reference

Question

The Python documentation seems unclear about whether parameters are passed by reference or value, and the following code produces the unchanged value ‘Original’

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.Change(self.variable)
        print self.variable

    def Change(self, var):
        var = 'Changed'

Is there something I can do to pass the variable by actual reference?

Answer

Parameters are passed by value. The reason people are confused by the behaviour is twofold:

  1. the parameter passed in is actually a reference to a variable (but the reference is passed by value)
  2. some data types are mutable, but others aren’t

So, if you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart’s delight, but if you rebind the reference in the method, the outer scope will know nothing about it, and after you’re done, the outer reference will still point at the original object. If out pass an immutable object to a method, you still can’t rebind the outer reference, and you can’t even mutate the object.

Okay, this is a little confusing. Let’s have some examples.

List – a mutable type

Let’s try to modify the list that was passed to a method:

def try_to_change_list_contents(the_list):
    print 'got', the_list
    the_list.append('four')
    print 'changed to', the_list

outer_list = ['one', 'two', 'three']

print 'before, outer_list =', outer_list
try_to_change_list_contents(outer_list)
print 'after, outer_list =', outer_list

Output:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

Since the parameter passed in is a reference to outer_list, not a copy of it, we can use the mutating list methods to change it and have the changes reflected in the outer scope.

Now let’s see what happens when we try to change the reference that was passed in as a parameter:

def try_to_change_list_reference(the_list):
    print 'got', the_list
    the_list = ['and', 'we', 'can', 'not', 'lie']
    print 'set to', the_list

outer_list = ['we', 'like', 'proper', 'English']

print 'before, outer_list =', outer_list
try_to_change_list_reference(outer_list)
print 'after, outer_list =', outer_list

Output:

before, outer_list = ['we', 'like', 'proper', 'English']
got ['we', 'like', 'proper', 'English']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'English']

Since the the_list parameter was passed by value, assigning a new list to it had no effect that the code outside the method could see. The the_list was a copy of the outer_list reference, and we had the_list point to a new list, but there was no way to change where outer_list pointed.

String – an immutable type

It’s immutable, so there’s nothing we can do to change the contents of the string

Now, let’s try to change the reference

def try_to_change_string_reference(the_string):
    print 'got', the_string
    the_string = 'In a kingdom by the sea'
    print 'set to', the_string

outer_string = 'It was many and many a year ago'

print 'before, outer_string =', outer_string
try_to_change_string_reference(outer_string)
print 'after, outer_string =', outer_string

Output:

before, outer_string = It was many and many a year ago
got It was many and many a year ago
set to In a kingdom by the sea
after, outer_string = It was many and many a year ago

Again, since the the_string parameter was passed by value, assigning a new string to it had no effect that the code outside the method could see. The the_string was a copy of theouter_string reference, and we had the_string point to a new list, but there was no way to change where outer_string pointed.

I hope this clears things up a little.

EDIT: It’s been noted that this doesn’t answer the question that @David originally asked, “Is there something I can do to pass the variable by actual reference?”. Let’s work on that.

How do we get around this?

As @Andrea‘s answer shows, you could return the new value. This doesn’t change the way things are passed in, but does let you get the information you want back out:

def return_a_whole_new_string(the_string):
    new_string = something_to_do_with_the_old_string(the_string)
    return new_string

# then you could call it like
my_string = return_a_whole_new_string(my_string)

If you really wanted to avoid using a return value, you could create a class to hold your value and pass it into the function or use an existing class, like a list:

def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
    new_string = something_to_do_with_the_old_string(stuff_to_change[0])
    stuff_to_change[0] = new_string

# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)

do_something_with(wrapper[0])

Although this seems a little cumbersome.

 

Reference

Immutable object

http://en.wikipedia.org/wiki/Immutable_object

In object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created.[1] This is in contrast to a mutable object, which can be modified after it is created. In some cases, an object is considered immutable even if some internally used attributes change but the object’s state appears to be unchanging from an external point of view. For example, an object that uses memoization to cache the results of expensive computations could still be considered an immutable object.

Immutable objects are often useful because they are inherently thread safe.[1] Other benefits are that they are simpler to understand and reason about and offer higher security than mutable objects.[1]

However, making an object immutable is usually inappropriate if the object contains a large amount of changeable data. Because of this, many languages allow for both immutable and mutable objects.

Python

In Python some built-in types (numbers, strings, tuples, frozensets) are immutable, but custom classes are generally mutable. To simulate immutability in a class, one should override attribute setting and deletion to raise exceptions:

class Immutable(object):
     """An immutable class with a single attribute 'value'."""
     def __setattr__(self, *args):
         raise TypeError("can't modify immutable instance")
     __delattr__ = __setattr__
     def __init__(self, value):
         # we can no longer use self.value = value to store the instance data
         # so we must explicitly call the superclass
         super(Immutable, self).__setattr__('value', value)

[python]time.clock vs time.time

September 19th, 2011 by bettermanlu

Recently I need to calculate the time cost for some test cases running on Linux.  After searching online, I got an answer: using time.clock or time.time. And I did a sample test on Windows with time.clock which works well. But when running it under Linux. The result is totally different.

My code as below which is quite simple by calling time.clock or time.time:

import time

print ‘——-’

start = time.clock( )

print ‘start  = ‘,start

time.sleep( 2 )

end = time.clock( )

print ‘end    = ‘,end

print ‘elapse = ‘,end – start

print ‘——-’
start = time.time( )

print ‘start  = ‘,start

time.sleep( 2 )

end = time.time( )

print ‘end    = ‘,end

print ‘elapse = ‘,end – start

The output are quite different on Linux and windows for time.clock function.

Linux Windows
—-time.clock—

start  =  0.01

end    =  0.01

elapse =  0.0

—-time.time—

start  =  1316423764.45

end   =  1316423766.45

elapse =  2.00015687943

—-time.clock—

start  =  1.5398325817e-06 #this is really small

end    =  2.00183702027

elapse =  2.00183548044

—-time.time—

start  =  1316423430.99

end    =  1316423432.99

elapse =  2.00199985504

From the above table, we can see that for time.clock, the elapsed time is ZERO which is not what we expected. So what does time.clock really do on different platforms?

From below descriptions copied from Python’s manual, we can see that for time.clock, it has totally different behavior.

time.clock()

On Unix, return the current processor time as a floating point number expressed in seconds. The precision, and in fact the very definition of the meaning of “processor time”, depends on that of the C function of the same name, but in any case, this is the function to use for benchmarking Python or timing algorithms.

On Windows, this function returns wall-clock(ie, the time on the clock on your wall) seconds elapsed since the first call to this function, as a floating point number, based on the Win32 function QueryPerformanceCounter. The resolution is typically better than one microsecond.

 

time.time()
Return the time as a floating point number expressed in seconds since the epoch, in UTC. Note that even though the time is always returned as a floating point number, not all systems provide time with a better precision than 1 second. While this function normally returns non-decreasing values, it can return a lower value than a previous call if the system clock has been set back between the two calls.

Conclusion

If you’re writing code that’s meant only for Windows, either will work (though you’ll use the two differently – no subtraction is necessary for time.clock()). If this is going to run on a Unix system or you want code that is guaranteed to be portable, you will want to use time.time().

Ref:

http://mrwlwan.wordpress.com/2008/09/19/python%EF%BC%9Atimeclock-vs-timetime/

http://stackoverflow.com/questions/85451/python-time-clock-vs-time-time-accuracy

 

[FW]Software Testing to Software Engineering

September 16th, 2011 by bettermanlu

Software Testing to Software Engineering

Full article is here: http://www.logigear.com/september-issue-2011/1110-vipul-gupta.html

读后感

当前离岸软件测试的变化:不再是之前的简单执行测试用例,而是要尽可能早的投入到软件的各个生命周期中,对测试软件做更深入的分析,使用更多的测试工具/平台及不同的测试策略(有哪些策略呢?),进行有针对的、多维度(功能,性能,安全等)的测试。 而文章最后多少有些让人反思,传统的软件测试评估数据(bug个数,用例个数)是否已经过时了?我们是否应该采用更好/更准确的指标数据呢?(specifications coverage, model coverage and code coverage, 还有其他的吗?)

 

[python]How to implement Singleton in Python

September 12th, 2011 by bettermanlu

Unlike other OOP language, such as C++/Java, which provides private access mechanism to prevent its constructor be accessed and then be instanced, Python doesn’t have such mechanism, i.e, “Private” instance variables that cannot be accessed except from inside an object don’t exist in Python.

So how to implement Singleton in Python without “Private” support? Overriding __new__ function is the key.  __new__ is a classmethod, and you can override it when you need to control the creation of a new instance.  __new__ is the first step of instance creation. It’s called first, and is responsible for returning a new instance of your class. In contrast, __init__ doesn’t return anything; it’s only responsible for initializing the instance after it’s been created. so use __init__ when you need to control initialization of a new instance. Below is the sample code of Singleton in Python.

class Singleton(object):

_instance = None

def __new__(cls, *args, **kwargs):

if not cls._instance:

cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)

return cls._instance

if __name__ == ‘__main__’:

s1=Singleton()

s2=Singleton()

if(id(s1)==id(s2)):

print “Same”

else:

print “Different”

Ref:

http://stackoverflow.com/questions/674304/pythons-use-of-new-and-init

http://www.python-cn.cn/yuyanjichu/2011/0507/10742.html

 

[python]datetime tip

August 23rd, 2011 by bettermanlu

Below code is to get the current date and the following one month date, then covert them to a string.

=====mydate.py=====

import datetime

today = datetime.datetime.now()

nextMonth = today + datetime.timedelta( days=30 )

startDate = today.strftime(“%Y-%m-%d”)
endDate = nextMonth.strftime(“%Y-%m-%d”)

print startDate, endDate.

 

[php]How to print SOAP requests/response?

August 8th, 2011 by bettermanlu

If you are working with PHP’s SOAPClient, and need to print out SOAP requests/response,  below is the simple way.

1. Enable SOAP trace option.

client = SOAPClient(“www.xxx.com/soap?wsdl”, array(‘trace’ => 1) );

2. Then calls

….

client.__soapCall(xxx)

echo “REQUEST: “. htmlentities(client.__getLastRequest( ) );

….

echo “REQUEST: “. htmlentities(client.__getLastResponse( ) );

If you have that much soap requests in your system, a decorator of SOAPClient probably is a better way. For details, please refer to http://stackoverflow.com/questions/1729345/logging-all-soap-request-and-responses-in-php

Ref:

http://www.php.net/manual/en/soapclient.soapclient.php

 

[http]HTTP GET and POST with Python

April 10th, 2011 by bettermanlu

There are several modules provided by python you can use to send HTTP GET/POST requests: httplib/urllib/urllib2.

In general, httplib module defines classes which implement the client side of the HTTP and HTTPS protocols.  It is normally not used directly — the module urllib uses it to handle URLs that use HTTP and HTTPS.

urllib module provides a high-level interface for fetching data across the WWW.  urllib2 module defines functions and classes which help in opening URLs (mostly HTTP) in a complex world — basic and digest authentication, redirections, cookies and more.

There are two good articles on how to use these modules.

urllib2 – The Missing Manual – HOWTO Fetch Internet Resources with Python

Make Yahoo! Web Service REST calls with Python

I’d like to highlight several tips and attentions on these modules.

1. Please use urllib2 instead of httplib if impossible. urlib2 provides a high-level interface which is more convenient. From below two functions, we can see that when using httplib, we need to specify more parameters.

def getUrlRating(url): # using httplib
params = urllib.urlencode({‘urlname’: url,’getinfo’:'Check Now’})
headers = {“Content-type”: “application/x-www-form-urlencoded”,”Accept”: “text/plain”}
conn = httplib.HTTPConnection(“global.sitesafety.trendmicro.com”,80)
conn.request(“POST”, “/result.php”, params, headers)
response = conn.getresponse()
print response.status, response.reason
data = response.read()
conn.close()
print ‘——\n’
print data
return

def getUrlRating2(url): #using urllib2
host = “http://global.sitesafety.trendmicro.com/result.php”
params = urllib.urlencode({‘urlname’: url,’getinfo’:'Check Now’})
req = urllib2.Request(host, params)
response = urllib2.urlopen(req)
data = response.read()
print response.info()
print ‘——\n’
print data
return

2. Please don’t include “http://” prefix for the first  parameter host of httplib.HTTPConnection, otherwise, you will meet a socket error:  socket.gaierror: (11001, ‘getaddrinfo failed’)

2. how to close urllib2 connection?

http://stackoverflow.com/questions/1522636/should-i-call-close-after-urllib-urlopen

The close method must be called on the result of urllib.urlopen, not on the urllib module itself.

The best approach: instead of x = urllib.urlopen(u) etc, use:

import contextlib

with contextlib.closing(urllib.urlopen(u)) as x:
   ...use x at will here...

The with statement, and the closing context manager, will ensure proper closure even in presence of exceptions.

3. If you don’t know how to determine the POST parameters by reading the submit page’s html source code, try to use Fiddler or Wireshark to capture the http traffic and find out the POST data. For example, below screenshot is the POST data for Trend Micro’s site safety checking page when submitting www.sina.com.cn as query parameter.

Below is corresponding code snippet.

host = “http://global.sitesafety.trendmicro.com/result.php”
params = urllib.urlencode({‘urlname’: ‘www.sina.com.cn’,'getinfo’:'Check Now’})
req = urllib2.Request(host, params)
response = urllib2.urlopen(req)
data = response.read()
print response.info()
print ‘——\n’
print data

[python] third-party python packages

February 18th, 2011 by bettermanlu

Today I’d like share several third-party python packages.

1. Py2Exe

http://www.py2exe.org/

py2exe converts Python scripts into executable Windows programs, able to run without requiring a Python installation.

The usage is quite simple, please refer to http://www.py2exe.org/index.cgi/Tutorial.

2.PyWin32

http://sourceforge.net/projects/pywin32/

Win32 API Wrapper

3. xlrd

http://pypi.python.org/pypi/xlrd

Library for developers to extract data from Microsoft Excel spreadsheet files

4. Celery & parallel processing

http://pypi.python.org/pypi/celery

Celery is an open source asynchronous task queue/job queue based on distributed message passing.

More Python based parallel processing information can be found at:  http://wiki.python.org/moin/ParallelProcessing

5. Read/write mysql through ODBC

Under Windows OS, we can access mysql database through ODBC.  Two packages need to be installed on the host machine.

PyWin32 and mysql-connector-odbc-5.1.5-win32.msi

http://sourceforge.net/projects/pywin32/

http://dev.mysql.com/downloads/connector/odbc/

Also you need to create a “MySQL ODBC 5.1 Driver” typed system data source with windows Administrative Tools.

—-Sample code—-

import odbc


con = odbc.odbc(“database1/user/password”)
cursor = con.cursor()
cursor.execute(‘select * from pba_components’)
for f in cursor.fetchall():
….

con.close()

[http] Python sample: Downloading file through HTTP protocol with multi-threads

February 14th, 2011 by bettermanlu

Free download manager is a popular tool that supports IE/FF to download files via HTTP, HTTPS and FTP.  One highlight of its features is its “download acceleration”. FDM splits files into several sections and downloads them simultaneously. Have you ever been curious about its implementations? Don’t worry, this article will shed some light on the basic theories behind it.

1. HTTP HEAD Request and HTTP Reponse Content-Length & Accept-Ranges Headers
The HEAD method is a standard HTTP method that acts as if I’ve made a GET request, but it returns only the headers and not the body. This allows me to find out some information about the resource without actually taking the time or using the bandwidth to download it.

For example, I can read the corresponding HTTP Response Content-Length header and determine the size of the resource.

Another important reponse’s header is

Accept-Ranges Header

This header indicates to the Web client that the server has the capability to handle range requests. There are only two valid formats for the Accept-Ranges header that are allowed according to the definition:

Accept-Ranges: bytes
Accept-Ranges: none

These basically indicate that the Web server does and does not accept range requests, respectively.

If Web server supports range requests, the client can then use below range header to download partial contents.

2. HTTP GET Request – Range Header
The Range header allows the HTTP client to request partial content, rather than the usual full content, by specifying a range of bytes it seeks to receive.

For example, to request the first 500 bytes of content,  the following Range header should be included in the request:

Range: bytes=0-499

A successful partial content response will be a 206 Partial Content.

With the above key points, we can write a python script:

3. Code sample: Multi-threads downloading file through HTTP protocol.

Basic workflow:
(1) send HTTP HEAD request to check whether Web server supports range request.
(2) If supports(“Accept-Ranges: bytes”), then read “Content-Length” header.
(3) Split the whole file into multiple blocks (100K bytes per block), and start #blocks HttpPartialDownloadThread to download each part.
(4) After all theads terminate, merge all partials into one big file.

############

#http_get_rangeRequest_multithread.py demo

#Download Fiddler2Setup.exe from www.getfiddler.com/dl/Fiddler2Setup.exe with multiple threads

#copyright: bettermanlu@gmail.com

########

import httplib

import string,time,shutil

from threading import *

doneCount = 0 #counter to count the finished thread number

#start of download thead class

class HttpPartialDownloadThread(Thread):

def __init__(self,hostURL,resourceURL,startByte,endByte,threadIndex):

Thread.__init__(self)

self.hostURL = hostURL

self.resourceURL = resourceURL

self.startByte = startByte

self.endByte = endByte

self.threadIndex = threadIndex

self.done = False

def run(self):

print ‘thread %s is running’ %self.threadIndex

self.partialDownload()

return

def partialDownload(self):

global doneCount

conn = httplib.HTTPConnection(self.hostURL)

conn.request(“GET”,self.resourceURL,headers={“Range”:”bytes=%s-%s” %(self.startByte,self.endByte)})

r1 = conn.getresponse()

print r1.status, r1.reason

file = open(“part_%s” %self.threadIndex,”wb”)

file.write(r1.read())

file.close()

self.done = True

doneCount += 1

conn.close()

return

#end of class

def mergeRanges(fileName,partialFileCount):

fout = file(‘%s’ %fileName, ‘wb’)

for i in range(0,partialFileCount):

fin = file(“part_%s”%i, ‘rb’)

shutil.copyfileobj(fin, fout, 65536)

fin.close()

fout.close()

def getContentLength(conn,resourceURL):

#send “HEAD” request to get the basic information of the resourceURL

conn.request(“HEAD”, resourceURL)

r1 = conn.getresponse()

print r1.status, r1.reason

#Note that you must have read the whole response before you can send a new request to the server.

#otherwise you will meet httplib.ResponseNotReady error, even you don’t need the body.

r1.read()

content_length = 0

#read “accept-ranges” header to see if server supports ranges request

accept_ranges = r1.getheader(“accept-ranges”)

if accept_ranges == “bytes”:

#read “content-length” header to get the length of the content section of the HTTP message in bytes

content_length = string.atoi(r1.getheader(“content-length”))

return content_length

def getRangeFileTest():

hostURL = “www.getfiddler.com”

resourceURL = “/dl/Fiddler2Setup.exe”

conn = httplib.HTTPConnection(hostURL)

contentLength = getContentLength(conn,resourceURL)

print contentLength

BLOCK_SIZE = 1000*100 #100K Bytes per block

if contentLength > 0:

#split the content into several parts: #BLOCK_SIZE per block.

blockNum = contentLength/BLOCK_SIZE

lastBlock = contentLength % BLOCK_SIZE

partialFileCount = 0

for i in range(0,blockNum+1):

startByte = BLOCK_SIZE*i

endByte = startByte + BLOCK_SIZE -1

if endByte > contentLength-1:

endByte = contentLength -1

if startByte < endByte:

downloadThread =  HttpPartialDownloadThread(hostURL,resourceURL,startByte,endByte,i)

downloadThread.start()

partialFileCount += 1

#ToDo: change it to event driven

while(doneCount < partialFileCount):

print “waiting all threads terminated.zzz…”

time.sleep(1)

#print doneCount,partialFileCount

print ‘Now merge them to one file’

mergeRanges(“test.exe”,partialFileCount)

if __name__ == ‘__main__’:

getRangeFileTest()

Ref:
1. Book “HTTP Developer’s Handbook” By Chris Shiflett
2. http://benramsey.com/archives/206-partial-content-and-range-requests/

Static Linking and Dynamic Linking

January 10th, 2011 by bettermanlu

Recently I was stucked by a question as what a “.LIB” file is for.  Two concepts  came into my mind, “static linking” and “dynamic linking”.  Is “.LIB” file for static linking? But I remembered that one type of dynamic linking also requires a “.LIB” file.  Are the two “.LIB” files the same?  Hope today’s  session can give you an answer.

Static Linking

Static libraries are used when you don’t want your final compiled application to have any dependencies. So to make it standalone, the compiler embeds all the code from the static library in the final executable and removes any dependencies it had. A static library is just a collection of object files. The overhead is huge. Each executable will have its own copy of all the functions. With small libraries with a few Kilobyte of overhead, it would be fine, but what about big libraries like MFC.

Dynamic Linking

Dynamic linking refers to linking at runtime rather than at compile time. Information is still embedded in the final executable but it’s the bare minimum for the loader (which loads the executable at runtime in the memory) to identify the DLL the program uses and load them with the application by mapping all the DLLs to the process’ address space. Dynamic linking has two forms depending on how the information is embedded in the final executable. They are Implicit Linking and Explicit Linking.

(1) Implicit Linking(aka. static load or load-time dynamic linking)

Implicit linking occurs at compile time when an application’s code makes a reference to an exported DLL function. When the source code for the calling executable is compiled, the DLL function call translates to an external function reference in the object code. To resolve this external reference, the application must link with the import library (.LIB file) that is produced when the DLL is built.

The import library only contains code to load the DLL and to implement calls to functions in the DLL. Finding an external function in an import library informs the linker that the code for that function is in a DLL. To resolve external references to DLLs, the linker simply adds information to the executable file that tells the system where to find the DLL code when the process starts up.

To implicitly link to a DLL, executables must obtain the following from the provider of the DLL:

  1. A header file (.H file) containing the declarations of the exported functions and/or C++ classes.
  2. An import library (.LIB files) to link with. The linker creates the import library when the DLL is built.
  3. The actual DLL (.DLL file).

(2) Explicit Linking(aka. dynamic load or run-time dynamic linking)

With explicit linking, applications must make a function call to explicitly load the DLL at run time. To explicitly link to a DLL, an application must:

  1. Call LoadLibrary() (or a similar function) to load the DLL and obtain a module handle.
  2. Call GetProcAddress() to obtain a function pointer to each exported function that the application wants to call. Because applications are calling the DLL’s functions through a pointer, the compiler does not generate external references, so there is no need to link with an import library.  Also no need the header file, only DLL is requried.
  3. Call FreeLibrary() when done with the DLL.

Please refer to http://msdn.microsoft.com/en-us/library/784bt7z7%28v=VS.80%29.aspx for an explicit linking example.

Most applications use implicit linking because it is the easiest linking method to use. However, there are times when explicit linking is necessary. Here are some common reasons to use explicit linking:

  1. The application does not know the name of a DLL that it will have to load until run time. For example, the application might need to obtain the name of the DLL and the exported functions from a configuration file.
  2. A process using implicit linking is terminated by the operating system if the DLL is not found at process startup. A process using explicit linking is not terminated in this situation and can attempt to recover from the error. For example, the process could notify the user of the error and have the user specify another path to the DLL.
  3. A process using implicit linking is also terminated if any of the DLLs it is linked to have a DllMain() function that fails. A process using explicit linking is not terminated in this situation.
  4. An application that implicitly links to many DLLs can be slow to start because Windows loads all of the DLLs when the application loads. To improve startup performance, an application can implicitly link to those DLLs needed immediately after loading and wait to explicitly link to the other DLLs when they are needed.
  5. Explicit linking eliminates the need to link the application with an import library. If changes in the DLL cause the export ordinals to change, applications using explicit linking do not have to re-link (assuming they are calling GetProcAddress() with a name of a function and not with an ordinal value), whereas applications using implicit linking must re-link to the new import library.

Ref:

http://www.tenouk.com/ModuleBB.html

http://msdn.microsoft.com/en-us/library/253b8k2c%28VS.80%29.aspx

http://www.aspfree.com/c/a/Code-Examples/Dynamic-Link-Libraries-Inside-Out/4/

« Previous Entries