『壹』 求助,如何將C函數指針傳遞給python
這個和用不用python沒啥關系,是數據來源的問題。 調用淘寶API,使用 api相關介面獲得你想要的內容,我 記得api中有相關的介面,你可以看一下介面的說明。 用python做爬蟲來進行頁面數據的獲齲。
『貳』 python如何傳遞給c++一個結構體指針前提是swig封
在封裝的代碼間傳遞指針你要確保他們運行在相同的地址空間里,還要保證指針指向的內存的生存期是安全的,否則這種思路就是錯誤的。實現方法舉例如下:
1、定義了C 結構體和函數如下
typedef struct NameAge
{
char name[20];
int age;
}NameAge , *NameAgePointer;
void test(NameAgePointer p) // 接收結構體指針
{
// do something with p...
}
2、python定義結構體如下
#python中結構體定義
class PyStruct():
def __init__(self, name, age):
self.name = name
self.age = age
fred = PyStruct("fred", 5)
3、假設把第1步里的test封裝成example模塊,python導入example(既然你都會swig了,這個過程就不啰嗦了)
>>>import example
>>>example.test(pointer(fred))
以上是基本思路,因為搭建開發環境和過程比較繁雜,沒有驗證過,但是應該沒有大問題
『叄』 C調用Python模塊傳參的問題 [
Py_BuildValue()函數可以和PyArg_ParseTuple()函數一樣識別一系列的格式串,但是輸入參數只能是值,而不能是指針。參考官方文檔https://docs.python.org/2/c-api/arg.html?highlight=py_buildvalue#Py_BuildValue
『肆』 python中,能對函數傳遞文件指針類型的參數嗎
如果你用C給Matlab寫過MEX程序,那麼這個問題是很容易理解的(好像每次討論Python問題時我總是把Matlab搬了出來…… 《在Matlab中把struct當成Python中的Dictionary使用》《Matlab和Python的幾種數據類型的比較》)。
既然提到了MEX,就簡單說一下:
一個Matlab可能形如
function ret=add3(a,b,c)
如果在C的層面實現這個函數,就會看到另一種景象:
void mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])
a,b,c三個參數的地址放在一個指針數組里,然後把這個指針數組的首地址作為參數prhs傳遞給函數,這說明Matlab函數的參數是傳遞指針的,而不是值傳遞。
縱然是傳遞的指針,但是卻不能在函數里改變實參的值,因為標記為「const」了。
Python是開放源碼的,我沒有看。所以下面很多東西是猜的。
Python在函數的參數傳遞時用的什麼手法?實驗一下(使用ActivePython2.5):
首先介紹一個重要的函數:
>>> help(id)
Help on built-in function id in mole __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.)
看最後括弧里那句:Hint:it's the object's address.(它是對象的地址)
有了這個函數,下面的事情就方便多了。
>>> a=0
>>> id(a)
3630228
>>> a=1
>>> id(a)
3630216
可以看出,給a賦一次值,a的address就改變了。在C的層面看,(也許真實情況不是下面的樣子,但作為一個類比應該還是可以的):
void * pa;
pa=malloc(sizeof(int));
*(int *)pa=0;
free(pa);
pa=malloc(sizeof(int));
*(int *)pa=1;
Python中每次賦值會改變變數的address,分配新的內存空間,所以Python中對於類型不像C那樣嚴格要求。
下面看看Python函數參數傳遞時到底傳的什麼:
有一個函數:
>>> def changeA(a):
... print id(a)
... a=100
... print id(a)
設定一個變數var1:
>>> var1=10
>>> id(var1)
3630108
>>> changeA(var1)
3630108
3631012
>>> var1
10
調用函數後,從兩次print的結果可以看出,傳遞確實是地址。但是即便如此,在函數內對形參的修改不會對實參造成任何實質的影響,因為對形參的重新賦值,只是改變了形參所指向的內存單元(changeA里兩次調用print id(a)得到不同的結果),卻沒有改變實參的指向。在C的層面看也許類似下面的情節:
void changeA(void * pa)
{
pa=malloc(sizeof(int));
*(int *)pa=100;
free(pa);
}
精通C的你一眼就看出這個函數永遠也改變不了它外面的世界。
也就是說雖然傳遞的是地址,但像changeA這樣的函數改變不了實參的值。
也許會感到困擾?不,我已經在Matlab中習慣了。
一個最典型的例子就是Matlab中刪除結構體成員的rmfield函數(參見《Matlab筆記三則》),
(Matlab版本7.0.1)
如果想刪除結構體patient的name成員,用
rmfield(patient, 'name');
是永遠達不到目的的(就像試圖用雙手抓住自己的領子,把自己提到空中);
迷途知返的做法是:
patient = rmfield(patient, 'name');
『伍』 python使用C函數返回的指針
manage_new_object返回類的動態對象,要返回簡單的指針,把manage_new_object改為return_xxx_pointer,具體名字記不得了,反正有這個模板,查閱boost文檔吧。
『陸』 python調用C++,如何傳遞數組指針
很多辦法都可以 如果你的c++對象是已有的代碼,可以用cpython包裝成Python對象,這些cpython包裝的對象有一個指針是指向 你要包裝的c++對象的,然後提供訪問c++對象的方法。比如你一顆樹可以包裝成Python對象,樹節點也包裝成Python對象!
『柒』 python如何傳遞給c++一個結構體指針前提是swig封裝的C++函數,請寫出代
在封裝的代碼間傳遞指針你要確保他們運行在相同的地址空間里,還要保證指針指向的內存的生存期是安全的,否則這種思路就是錯誤的。實現方法舉例如下:
1、定義了C
結構體和函數如下
typedef
struct
NameAge
{
char
name[20];
int
age;
}NameAge
,
*NameAgePointer;
void
test(NameAgePointer
p)
//
接收結構體指針
{
//
do
something
with
p...
}
2、python定義結構體如下
#python中結構體定義
class
PyStruct():
def
__init__(self,
name,
age):
self.name
=
name
self.age
=
age
fred
=
PyStruct("fred",
5)
3、假設把第1步里的test封裝成example模塊,python導入example(既然你都會swig了,這個過程就不啰嗦了)
>>>import
example
>>>example.test(pointer(fred))
以上是基本思路,因為搭建開發環境和過程比較繁雜,沒有驗證過,但是應該沒有大問題
『捌』 怎麼在python調用C函數的時候實現指針參數
Python寫程序原則是所有進來的字元串(讀文件,爬網頁),一進來就decode,處理完之後在要輸出的地方在encode。題主讀入(read)和輸出(print)在一行里,要在win下面想不出錯就這么寫 print response.decode('utf-8').encode('gbk')
『玖』 python怎麼調用c的動態鏈接庫
Python調用C/C++動態鏈接庫的需求
在自動化測試過程中,難免會遇到語言混合使用的情況,這不,我們也遇到了。初步決定採用Robot Framework作為自動化測試框架後,其支持Java和Python,而Python作為主流的語言,怎麼能放棄使用它的機會^_^。 然而產品採用是古老90年代開發的C/S結構,因為古老,當時也沒有考慮到對產品的測試進行自動化,Client端並沒有預留CLI(Command Line interface)形式的介面,真是雪上加霜啊。
那怎麼自動化?採用AutoIT來對客戶端界面進行自動化測試?可惜AutoIT對當初開發採用的控制項識別不是很好,如果採用控制項所在位置來進行控制的方式,又會導致自動化測試並不是很穩定。那麼!!!只有自己開發介面了,目前在Client端開發出CLI形式的介面,將其封裝為DLL,然後在Robot FrameWork框架中採用Python對DLL進行調用。任務艱巨哪!
Python調用DLL例子
示例一
首先,在創建一個DLL工程(本人是在VS 2005中創建),頭文件:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif
extern "C"
{
HELLO_API int IntAdd(int , int);
}
CPP文件:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.cpp
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API int IntAdd(int a, int b)
{
return a + b;
}
這里有兩個注意點:
(1)弄清楚編譯的時候函數的調用約定採用的__cdecl還是__stdcall,因為根據DLL中函數調用約定方式,Python將使用相應的函數載入DLL。
(2)如果採用C++的工程,那麼導出的介面需要extern "C",這樣python中才能識別導出的函數。
我的工程中採用__cdecl函數調用約定方式進行編譯鏈接產生hello.dll,然後Python中採用ctypes庫對hello.dll進行載入和函數調用:
[python] view plain 在CODE上查看代碼片派生到我的代碼片from ctypes import *
dll = cdll.LoadLibrary('hello.dll');
ret = dll.IntAdd(2, 4);
print ret;
OK,一個小例子已經完成了,如果你感興趣,但還沒試過,那就嘗試一下吧。
示例二
示例一隻是一個"hello world"級別的程序,實際運用中更多的需要傳遞數據結構、字元串等,才能滿足我們的需求。那麼這個示例將展示,如何傳遞數據結構參數,以及如何通過數據結構獲取返回值。
首先編寫DLL工程中的頭文件:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.h
#ifdef EXPORT_HELLO_DLL
#define HELLO_API __declspec(dllexport)
#else
#define HELLO_API __declspec(dllimport)
#endif
#define ARRAY_NUMBER 20
#define STR_LEN 20
struct StructTest
{
int number;
char* pChar;
char str[STR_LEN];
int iArray[ARRAY_NUMBER];
};
extern "C"
{
//HELLO_API int IntAdd(int , int);
HELLO_API char* GetStructInfo(struct StructTest* pStruct);}
CPP文件如下:
[cpp] view plain 在CODE上查看代碼片派生到我的代碼片//hello.cpp
#include <string.h>
#define EXPORT_HELLO_DLL
#include "hello.h"
HELLO_API char* GetStructInfo(struct StructTest* pStruct){
for (int i = 0; i < ARRAY_NUMBER; i++)
pStruct->iArray[i] = i;
pStruct->pChar = "hello python!";
strcpy (pStruct->str, "hello world!");
pStruct->number = 100;
return "just OK";
}
GetStructInfo這個函數通過傳遞一個StructTest類型的指針,然後對對象中的屬性進行賦值,最後返回"just OK".
編寫Python調用代碼如下,首先在Python中繼承Structure構造一個和C DLL中一致的數據結構StructTest,然後設置函數GetStructInfo的參數類型和返回值類型,最後創建一個StructTest對象,並將其轉化為指針作為參數,調用函數GetStrcutInfo,最後通過輸出數據結構的值來檢查是否調用成功:
[python] view plain 在CODE上查看代碼片派生到我的代碼片from ctypes import *
ARRAY_NUMBER = 20;
STR_LEN = 20;
#define type
INTARRAY20 = c_int * ARRAY_NUMBER;
CHARARRAY20 = c_char * STR_LEN;
#define struct
class StructTest(Structure):
_fields_ = [
("number", c_int),
("pChar", c_char_p),
("str", CHARARRAY20),
("iArray", INTARRAY20)
]
#load dll and get the function object
dll = cdll.LoadLibrary('hello.dll');
GetStructInfo = dll.GetStructInfo;
#set the return type
GetStructInfo.restype = c_char_p;
#set the argtypes
GetStructInfo.argtypes = [POINTER(StructTest)];objectStruct = StructTest();
#invoke api GetStructInfo
retStr = GetStructInfo(byref(objectStruct));#check result
print "number: ", objectStruct.number;
print "pChar: ", objectStruct.pChar;
print "str: ", objectStruct.str;
for i,val in enumerate(objectStruct.iArray):
print 'Array[i]: ', val;
print retStr;
總結
1. 用64位的Python去載入32位的DLL會出錯
2. 以上只是些測試程序,在編寫Python過程中盡可能的使用"try Except"來處理異常3. 注意在Python與C DLL交互的時候位元組對齊問題4. ctypes庫的功能還有待繼續探索