在封裝的代碼間傳遞指針你要確保他們運(yùn)行在相同的地址空間里,還要保證指針指向的內(nèi)存的生存期是安全的,否則這種思路就是錯(cuò)誤的。實(shí)現(xiàn)方法舉例如下:
創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、陜西網(wǎng)絡(luò)推廣、成都小程序開發(fā)、陜西網(wǎng)絡(luò)營銷、陜西企業(yè)策劃、陜西品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供陜西建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com
1、定義了C
結(jié)構(gòu)體和函數(shù)如下
typedef
struct
NameAge
{
char
name[20];
int
age;
}NameAge
,
*NameAgePointer;
void
test(NameAgePointer
p)
//
接收結(jié)構(gòu)體指針
{
//
do
something
with
p...
}
2、python定義結(jié)構(gòu)體如下
#python中結(jié)構(gòu)體定義
class
PyStruct():
def
__init__(self,
name,
age):
self.name
=
name
self.age
=
age
fred
=
PyStruct("fred",
5)
3、假設(shè)把第1步里的test封裝成example模塊,python導(dǎo)入example(既然你都會(huì)swig了,這個(gè)過程就不啰嗦了)
import
example
example.test(pointer(fred))
以上是基本思路,因?yàn)榇罱ㄩ_發(fā)環(huán)境和過程比較繁雜,沒有驗(yàn)證過,但是應(yīng)該沒有大問題
在封裝的代碼間傳遞指針你要確保他們運(yùn)行在相同的地址空間里,還要保證指針指向的內(nèi)存的生存期是安全的,否則這種思路就是錯(cuò)誤的。實(shí)現(xiàn)方法舉例如下:
1、定義了C 結(jié)構(gòu)體和函數(shù)如下
typedef struct NameAge
{
char name[20];
int age;
}NameAge , *NameAgePointer;
void test(NameAgePointer p) // 接收結(jié)構(gòu)體指針
{
// do something with p...
}
2、python定義結(jié)構(gòu)體如下
#python中結(jié)構(gòu)體定義
class PyStruct():
def __init__(self, name, age):
self.name = name
self.age = age
fred = PyStruct("fred", 5)
3、假設(shè)把第1步里的test封裝成example模塊,python導(dǎo)入example(既然你都會(huì)swig了,這個(gè)過程就不啰嗦了)
import example
example.test(pointer(fred))
以上是基本思路,因?yàn)榇罱ㄩ_發(fā)環(huán)境和過程比較繁雜,沒有驗(yàn)證過,但是應(yīng)該沒有大問題
如果你用C給Matlab寫過MEX程序,那么這個(gè)問題是很容易理解的(好像每次討論P(yáng)ython問題時(shí)我總是把Matlab搬了出來…… 《在Matlab中把struct當(dāng)成Python中的Dictionary使用》《Matlab和Python的幾種數(shù)據(jù)類型的比較》)。
既然提到了MEX,就簡(jiǎn)單說一下:
一個(gè)Matlab可能形如
function ret=add3(a,b,c)
如果在C的層面實(shí)現(xiàn)這個(gè)函數(shù),就會(huì)看到另一種景象:
void mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])
a,b,c三個(gè)參數(shù)的地址放在一個(gè)指針數(shù)組里,然后把這個(gè)指針數(shù)組的首地址作為參數(shù)prhs傳遞給函數(shù),這說明Matlab函數(shù)的參數(shù)是傳遞指針的,而不是值傳遞。
縱然是傳遞的指針,但是卻不能在函數(shù)里改變實(shí)參的值,因?yàn)闃?biāo)記為“const”了。
Python是開放源碼的,我沒有看。所以下面很多東西是猜的。
Python在函數(shù)的參數(shù)傳遞時(shí)用的什么手法?實(shí)驗(yàn)一下(使用ActivePython2.5):
首先介紹一個(gè)重要的函數(shù):
help(id)
Help on built-in function id in module __builtin__:
id(...)
id(object) - integer
Return the identity of an object. This is guaranteed to be unique among
simultaneously existing objects. (Hint: it's the object's memory address.)
看最后括號(hào)里那句:Hint:it's the object's address.(它是對(duì)象的地址)
有了這個(gè)函數(shù),下面的事情就方便多了。
a=0
id(a)
3630228
a=1
id(a)
3630216
可以看出,給a賦一次值,a的address就改變了。在C的層面看,(也許真實(shí)情況不是下面的樣子,但作為一個(gè)類比應(yīng)該還是可以的):
void * pa;
pa=malloc(sizeof(int));
*(int *)pa=0;
free(pa);
pa=malloc(sizeof(int));
*(int *)pa=1;
Python中每次賦值會(huì)改變變量的address,分配新的內(nèi)存空間,所以Python中對(duì)于類型不像C那樣嚴(yán)格要求。
下面看看Python函數(shù)參數(shù)傳遞時(shí)到底傳的什么:
有一個(gè)函數(shù):
def changeA(a):
... print id(a)
... a=100
... print id(a)
設(shè)定一個(gè)變量var1:
var1=10
id(var1)
3630108
changeA(var1)
3630108
3631012
var1
10
調(diào)用函數(shù)后,從兩次print的結(jié)果可以看出,傳遞確實(shí)是地址。但是即便如此,在函數(shù)內(nèi)對(duì)形參的修改不會(huì)對(duì)實(shí)參造成任何實(shí)質(zhì)的影響,因?yàn)閷?duì)形參的重新賦值,只是改變了形參所指向的內(nèi)存單元(changeA里兩次調(diào)用print id(a)得到不同的結(jié)果),卻沒有改變實(shí)參的指向。在C的層面看也許類似下面的情節(jié):
void changeA(void * pa)
{
pa=malloc(sizeof(int));
*(int *)pa=100;
free(pa);
}
精通C的你一眼就看出這個(gè)函數(shù)永遠(yuǎn)也改變不了它外面的世界。
也就是說雖然傳遞的是地址,但像changeA這樣的函數(shù)改變不了實(shí)參的值。
也許會(huì)感到困擾?不,我已經(jīng)在Matlab中習(xí)慣了。
一個(gè)最典型的例子就是Matlab中刪除結(jié)構(gòu)體成員的rmfield函數(shù)(參見《Matlab筆記三則》),
(Matlab版本7.0.1)
如果想刪除結(jié)構(gòu)體patient的name成員,用
rmfield(patient, 'name');
是永遠(yuǎn)達(dá)不到目的的(就像試圖用雙手抓住自己的領(lǐng)子,把自己提到空中);
迷途知返的做法是:
patient = rmfield(patient, 'name');
dk 可能是調(diào)用Create_Data前開辟的一個(gè)空間,dkLen傳入該空間大小,以方便函數(shù)Create_Data寫入結(jié)果到指針指向的空間。