當前位置:首頁 » 編程語言 » python編譯so

python編譯so

發布時間: 2022-02-27 19:33:40

A. python 怎麼調用so文件

當需要採用調用c++的程序的時候,需要對原有的數據加一個extern "C"封裝一下即可。

採用g++編譯的代碼也需要的,原因可能是因為c++編譯器編譯後的二進制so文件中,對c++的函數進行了重新的命名導致的。
extern "C" {
Foo* Foo_new(){ return new Foo(); }
void Foo_bar(Foo* foo){ foo->bar(); }
}
以下兩個網頁又更詳細的介紹
http://blog.waterlin.org/articles/using-python-ctypes-to-link-cpp-library.html

http://stackoverflow.com/questions/145270/calling-c-c-from-python

最後需要補充的一個問題是:當我調用so文件的時候,會發生一個有趣的現象:

我把python放到streaming找運行的時候,發現streaming始終查找不到so,但是數據卻是被上傳到hadoop的對應的work目錄下。

後來定位到原因:

是python載入動態庫方面是默認從系統lib庫上查找庫文件。
我的目錄在當前目錄下,所以需要從libdy.so變為./libdy.so

B. python *.so 文件 怎麼生成的

openstack是最近3年學習python的人最值得學習的一個雲計算框架。 OpenStack 包含兩個主要模塊:Nova 和 Swift,前者是 NASA 開發的虛擬伺服器部署和業務計算模塊;後者是 Rackspace開發的分布式雲存儲模塊,兩者可以一起用,也可以分開單獨用。

C. 如何編譯C++文件為Python擴展模塊

大概有三種常用方法:
1>使用ctypes模塊來調用C寫的共享庫,比如:
[python] view plain print?
#測試ctypes調用linux動態庫的能力
from ctypes import *
lib = CDLL("libc.so.6")
printf = lib.printf
printf("Hello World\n")

#查找動態庫
from ctypes.util import find_library
print find_library('c')
output = CDLL(find_library("c")).printf
output("測試成功!\n")
但是用它來調用C++寫的so就不太合適,因為編譯時c++函數名修飾會給你的函數取一個特殊的字元串,你不能在你的python代碼里直接使用此函數名,除非你使用的是修飾後的函數名。(在linux下你可以用nm來查看so中的函數名)

2>用C來寫python的擴展模塊,這個沒怎麼用過,以後使用時再記錄在此。
3>用C++來寫python擴展模塊:
我是使用Boost.Python來寫擴展的,先上工作中的代碼片段:

[python] view plain print?
#include <boost/python.hpp> //包含boost.python頭文件
#include <cstdio>
#include <string>

using namespace boost::python;//引入命令空間

class lshw //定義一個類
{
public:
lshw();
virtual ~lshw();

void scan_device();
string get_xml();

private:
hwNode *computer;
};

lshw::lshw()
{
computer = new hwNode("computer", hw::system);
}

lshw::~lshw()
{
if (computer)
delete computer;
}

void lshw::scan_device()
{
enable("output:numeric");
disable("output:sanitize");
scan_system(*computer);
}

string lshw::get_xml()
{
return computer->asXML();
}

void hello()
{
std::cout << "Hello World!" <<std::endl;
}

BOOST_PYTHON_MODULE(lshw)
{
class_<lshw, boost::nonable > ("lshw", "This is a lshw project python extend", init<>())//導出類中的方法
.def("scan_device", &lshw::scan_device)
.def("get_xml", &lshw::get_xml)
;
def("hello",&hello);//導出方法
}
使用boost.python其實結構很簡單,你只要寫很少的boost.python的代碼,你可以把大部分的精力放在C++功能代碼上,花很少的精力就可以把它擴展成python的模塊。下面是我在Ubuntu11.10上的編譯過程:

首先安裝boost.python:
sudo apt-get install libboost-python1.46.1
再來編譯生成so共享庫文件:
g++ -shared -fPIC lshw.cc -o lshw.so -lboost_python
使用:
[python] view plain print?
import lshw
hw = lshw.lshw()
lshw.hello()
hw.scan_device()
xml = self.hw.get_xml()

D. python擴展的c代碼在哪裡寫

在哪裡寫都可以啊,重要的是編譯過程。給你介紹下編譯過程吧。



在windows和linux下面,對C擴展的編譯方法是不一樣的,我們先來看windows版的。


我們用C實現一個簡單的加法。
首先新建一個文件add.c,代碼如下:

#include<Python.h>;
staticPyObject*add(PyObject*self,PyObject*args);
//一定聲明為static,把他們限制在這個文件范圍里。幾乎所有的參數都是PyObject類型,在python,每個東西都是object。
staticPyObject*add(PyObject*self,PyObject*args)
{
intx=0;
inty=0;
intz=0;
if(!PyArg_ParseTuple(args,"i|i",&x,&y))
returnNULL;
/*第一個參數是self,這個是python用的,每個函數都要有。我們暫時不管。args是一個參數列表。她把所有的參數都整合成一個string。所以
我們需要從這個string里來解析我們的參數。PyArg_ParseTuple來完成這個任務。第一個參數是args,就是我們要轉換的參數。第二個是格式符號。
「s」代表是個string。從args里提取一個參數就寫"s",兩個的話就寫"s|s",如果是一個string,一個int,就寫"s|i",和printf差不多。第三個
參數就是提取出來的參數放置的真正位置。必須傳遞這個參數的地址。對於add,他將提取兩個參數。分別是x和y。*/
z=x+y;
returnPy_BuildValue("i",z);
/*調用完之後我們需要返回結果。這個結果是c的type或者是我們自己定義的類型。必須把他轉換成PyObject,讓python認識。這個用Py_BuildValue
來完成。他是PyArg_ParseTuple的逆過程。他的第一個參數和PyArg_ParseTuple的第二個參數一樣,是個格式化符號。第三個參數
是我們需要轉換的參數。Py_BuildValue會把所有的返回只組裝成一個tutple給python。*/
}
staticPyMethodDefaddMethods[]=
{
{"add",add,METH_VARARGS,"Executeashellcommand."},
{NULL,NULL,0,NULL}
};
/*這個是一個c的結構。他來完成一個映射。我們需要把我們擴展的函數都映射到這個表裡。表的第一個欄位是python真正認識的。是python里的方法名字。第二個欄位是python里的這個方法名字的具體實現的函數名。在python里調用add,真正執行的是用c寫的add函數。第三個欄位是METH_VARARGS,他告訴python,add是調用c函數來實現的。第四個欄位是這個函數的說明。如果你在python里來help這個函數,將顯示這個說明。相當於在python里的函數的文檔說明。*/
PyMODINIT_FUNCinitadd()
{
Py_InitMole("add",addMethods);
}
/*注意,這個函數的名字不能改動。必須是init+模塊名字。我們的模塊名字是add。所以這個函數是initadd()。
這樣python在導入add的模塊時候,才會找到這個函數,並調用。這個函數調用Py_InitMole來將模塊名字和映射表結合在一起。他表示,add這個模塊使用addMethods這個映射表。python應該這樣導入我們的mole的.*/

新建一個setup.py,內容如下:

fromdistutils.coreimportsetup,Extension
mole1=Extension('add',sources=['add.c'])
setup(name='PackageName',version='1.0',description='Thisisademopackage',ext_moles=[mole1])

組建:(由於我的機器上裝了mingw,所以指定了mingw32。默認的編譯器是vs2008。參考:

python setup.py build--compiler=mingw32

執行後會在當前目錄生成一個build目錄及文件:

buildlib.win32-2.6add.pyd

將add.pyd拷貝到當前目錄,並寫一個測試文件test.py,代碼如下:

import add
print add.add(3,4)

執行一下,輸出為7

OK,基本上就是如此了。

在linux下的話,會有少許不同.
即直接用makefile將add.c編譯成.so,python可以直接import,makefile代碼如下:

PYLIB=/usr/bin
PYINC=/usr/include/python2.6
all:add.c
gccadd.c-g-I$(PYINC)-shared-L$(PYLIB)-lpython2.6-oadd.so
clean:
rm-fadd.so

用同樣的測試代碼,可以測試通過。

E. windows安裝mod_python未生成mod_python.so

在windows上需要.so是非常奇怪的……因為那是linux下動態鏈接庫的拓展名。windows下是dll。

題主最好轉到linux下去做這些。

F. 【python-C相互調用】python里的dict如何作為參數傳入.so中的c語言函數

#include<stdio.h>
#include<stdlib.h>
#include<Python.h>

staticPyObject*
wmf_reverse(PyObject*self,PyObject*args,PyObject*kwargs){
staticchar*kwlist[]={"name",NULL};
char*name=NULL;
PyObject*retval=NULL;

//問題1:只取一個字元串,format應該是"s"
//>>>if(PyArg_ParseTupleAndKeywords(args,keyds,"isi",kwlist,&name))
if(PyArg_ParseTupleAndKeywords(args,kwargs,"s",kwlist,&name)){
retval=(PyObject*)Py_BuildValue("i",1);
printf("%s ",name);
//問題2:不要釋放
//>>>free(name);
}else{
retval=(PyObject*)Py_BuildValue("i",0);
}
returnretval;
}

staticPyMethodDef
wmf_methods[]={
{"reverse",(PyCFunction)wmf_reverse,METH_VARARGS|METH_KEYWORDS,"reverse"},
//問題3:方法定義表,應該用一條空記錄來表示結束。
{NULL,NULL,0,NULL},
};

//問題4:沒有定義mole
staticstructPyMoleDef
wmf_mole={
PyMoleDef_HEAD_INIT,
"wmf",/*nameofmole*/
NULL,/*moledocumentation,maybeNULL*/
-1,/*sizeofper-interpreterstateofthemole,
or-.*/
wmf_methods,
};

//問題5:入口函數要聲明為:PyMODINIT_FUNC
PyMODINIT_FUNC
PyInit_wmf(void){
//問題6:Py_InitMole要初始化的是模塊,不是方法。所以傳方法定義是錯誤的。
//另外,python2.x是用Py_Init_mole,python3.x改用PyMole_Create了。
//兩者略有差別,自己注意一下吧。這里我用的是python3.x。
//Py_InitMole("wmf",ExtestMethods);
PyObject*m;
m=PyMole_Create(&wmf_mole);
if(m==NULL){
returnNULL;
}
returnm;
}

G. python調用動態庫(並且動態庫依賴其它動態庫)

用depends看一下導出了沒有?一般只要標准格式導出就可以使用的。

H. python怎麼調用安卓的.so文件

調用不了的,CPU架構都不一樣,一個是x86指令集,一個是arm指令集,怎麼調?
就算是指令集一樣的,你windows的程序也調用不了Linux的so庫。

I. python程序py文件能做成so文件嗎

可以
一、環境准備
安裝cython,以及gcc編譯環境
wget get-pip.py
python get-pip.py

pip install cython
yum install -y gcc python-devel

二、編寫測試腳本
test.py,內容如下
import os
def test():
print os.path.realpath('.')

三、將其拷貝到python系統路徑
/usr/lib/python2.7/site-packages/test
在test目錄下創建__init__.py, 與 test.py 的文件
test.py 上面內容如上所示

四、腳本測試
python
>>> import lyh.test
>>> lyh.test.test()

五、編譯so文件
以下操作均在 /usr/lib/python2.7/site-packages/test 路徑下執行

1. cython test.py
2. gcc -c -fPIC -I/usr/include/python2.7/ test.c
3. gcc -shared test.o -o test.so

六、驗證so文件的可用性
1. 移除/usr/lib/python2.7/site-packages/test/test.py 文件,只保留 test.so文件
test
├── __init__.py
└── test.so
2.
python
>>> import test.test
>>> test.test.test()

可以執行

驗證完成
七、使用setup.py 編譯so
1. 編寫setup.py文件,位於/usr/lib/python2.7/site-packages/test,內容如下:

from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_moles = cythonize("test.py")
)
2.然後運行
setup.py build_ext --inplace

J. 請教Python 從 egg 中 import so 文件的正確姿勢

我寫了一個包,用

python setup.py install

安裝後會在site-package目錄下得到一個.egg 的文件,然後可以在 python 中 import 這個包。 問題是,我在setup.py文件中包含了 package_data,是一個名為xxx.so的動態庫文件,這個庫文件在 install 之後也被正確包含進那個.egg 文件里了(把.egg 重命名成.zip 解壓後可以確認)。 但是,如果只用這個.egg 文件,那麼包里的一行代碼

from . import xxx

就會報錯

ImportError: cannot import name 'xxx'

奇怪的是,如果我重命名.zip 然後解壓成文件夾,from . import xxx就能正常載入那個動態庫了。

請問熟悉 Python 的 V 友這種情況該如何解決?謝謝!

我後來在`setup.py`中的`setup()`中加入了一條`zip_safe=False`來生成 folder 而不是 egg,解決了問題,但不知道有沒有更優雅的解決方案?

熱點內容
安卓背面是什麼字母 發布:2025-01-11 06:37:55 瀏覽:211
個人小程序怎麼購買雲伺服器 發布:2025-01-11 06:33:08 瀏覽:908
手機mc怎麼玩伺服器國際服 發布:2025-01-11 06:18:33 瀏覽:157
win2008ftp中文亂碼 發布:2025-01-11 06:10:03 瀏覽:868
平板配置為什麼這么低 發布:2025-01-11 06:05:30 瀏覽:622
可編程視頻 發布:2025-01-11 06:03:24 瀏覽:785
java多線程編程實戰 發布:2025-01-11 06:03:17 瀏覽:631
圖的演算法java 發布:2025-01-11 05:57:07 瀏覽:483
梯形圖編譯器 發布:2025-01-11 05:56:26 瀏覽:260
安卓framework編譯 發布:2025-01-11 05:55:00 瀏覽:696