之前講了Python調用C語言的基本方法,但是只能進行最簡單的操作。現在我們就來講講如何Python如何操作C語言指針。
掌握調用指針的方法,我們首先要了解2個函數byref和POINTER,還是先看看他們的doc吧
1.byref

2.POINTER(這一定是個不合格的程序員寫的,沒有留doc
)

好吧,byref翻譯過來就是:返回一個C語言的指針,只能用作函數的參數,和C語言傳入參數時使用&差不多的意思(個人理解哈)。POINTER沒寫doc,不過個人理解是將事物指針化,和C語言中初始化變量時使用 * 相當,不過不能用作參數。如果這部分有錯請留言!!!
接下來我們看個實例吧。
Example 1:
首先附上DLL代碼,代碼中參數和返回值均指針化了
#include "stdafx.h"
#include <stdio.h>
#define DLLAPI extern "C" _declspec(dllexport)
typedef struct Testdll
{
int a;
char* b;
}testdll;
DLLAPI testdll* test(testdll* t)
{
t->a=t->a+t->a;
printf("%d\n%s\n",t->a,t->b);
return t;
}
然后附上python代碼,就是拿上一次的代碼改了改,節約時間,勿噴!!
#coding=gbk
from ctypes import *
dllpath='C:\\Users\\***\\Documents\\Visual Studio 2010\\Projects\\EasyDll\\Release\\EasyDll.dll'
dll=CDLL(dllpath)
a=c_int(125)
b=c_char_p('Hello world,Hello Chengdu')
class testdll(Structure):
_fields_=[('a',c_int),
('b',c_char_p)]
t=testdll()#初始化結構體
t.a=a
t.b=b
dll.test.restype=POINTER(testdll)#確定test這個函數的返回值的類型
t=dll.test(byref(t))#執行函數
print t.contents.a
print t.contents.b
x=raw_input('any key to continue')
好吧,我們看見這個和第二部分的代碼基本差不多。不同的地方有3個。
1.dll.test.restype中,test的返回值類型使用了POINTER函數,也就是說,如果一個鏈接庫中函數返回值有指針,那么在Python中賦予函數返回值的時候就需要使用POINTER將結構體指針話
2.調用鏈接庫的test函數時,使用了byref函數。意思若鏈接庫里面的函數參數為指針,那么python中參數參數需要用byref取結構體地址
3.在獲取結構體值的時候,指針類型結構體里面的值是在contents里面。如果python接受到一個指針類型的結構體,那么他們的值全部都在contents里面
但是,呵呵,一運行的時候你會發現一個非常非常奇怪的現象。

為毛會這樣,接收到的值全部為空????????????
我將代碼進行一下小小的改動

然后運行

結果完全正確,我陷入了沉思~~~
為什么會這樣?為了探究這個問題,我們再一次修改代碼,添加一行如圖畫紅圈所示。

執行
我可以看到,在第一個t=dll.test(byref(t))中,執行完了之后t其實就已經被釋放掉了。至於原因,不再這里長篇大論了,后面再詳談~~~,大家暫時先注意一下這個問題就行了~
