Tiết lộ:Đã giải quyết một phần (xem phần cuối).
Sau đây là một ví dụ mã sử dụng nhúng Python:
#include
int main(int argc, char** argv)
{
Py_SetPythonHome(đối số[1]);
Khởi tạo Py();
PyRun_SimpleString("in \"Xin chào!\"");
Py_Hoàn tất();
trả về 0;
}
Tôi chạy nó trên Linux openSUSE 42.2 và gcc 4.8.5 (nhưng tôi cũng gặp vấn đề tương tự trên openSUSE 13.2 và gcc 4.8.3 hoặc RedHat 6.4 và gcc 4.4.7).
Tôi đã biên dịch cả phiên bản tĩnh và động cho Python 2.7.9 (nhưng tôi gặp vấn đề tương tự với Python 2.7.13).
Tôi biên soạn các ví dụ được liên kết tới phiên bản tĩnh của Python bằng lệnh sau:
g++ hello.cpp -o xin chào \
-Tôi /home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/static/include/python2.7 \
-L /home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/static/lib \
-l python2.7 -l pthread -l tiện ích -l dl
Nếu tôi thực hiện ví dụ của mình với phiên bản tĩnh của Python trong các đối số thì nó hoạt động.
Nếu tôi thực hiện nó trên phiên bản động của Python trong đối số, tôi nhận được lỗi sau (nó xảy ra tại Py_Khởi tạo()
ở giữa):
> ./xin chào /home/caduchon/softs/python/2.7.9/64/gcc/4.8.5/dynamic
Lỗi nghiêm trọng của Python: PyThreadState_Get: không có luồng hiện tại
Đã hủy bỏ (đã đổ lõi)
Tôi không hiểu tại sao nó lại hiệu quả với phiên bản tĩnh mà lại không hiệu quả với phiên bản động. Tôi có thể giải quyết vấn đề này như thế nào?
biên tập:Tập lệnh tôi sử dụng để cài đặt Python như sau:
#!/thùng/bash
WORKDIR=/home/caduchon/tmp/install_python_2_7_13
ARCHIVEDIR=/home/caduchon/downloads/python
PHIÊN BẢN PYTHON='2.7.13'
EZ_SETUP_VERSION='0.9'
PHIÊN BẢN SETUPTOOLS='34.1.0'
PHIÊN BẢN CYTHON='0.25.2'
PHIÊN BẢN NUMPY='1.12.0'
PHIÊN BẢN SCIPY='0.18.1'
MATPLOTLIB_VERSION='2.0.0'
CÀI ĐẶT=/home/caduchon/softs/python/$PYTHON_VERSION/64/gcc/4.8.5
LAPACKDIR=/home/caduchon/softs/lapack/3.6.1/64/gcc/4.8.5
### Tkinter ###
echo "Cài đặt Tkinter"
sudo apt-get cài đặt tk-dev
### Thư mục làm việc ###
echo "Tạo workdir"
mkdir -p $WORKDIR/tĩnh
mkdir -p $WORKDIR/động
Trăn
đối với x trong tĩnh động
LÀM
echo "Cài đặt Python ($x)"
đĩa $WORKDIR/$x
echo " trích xuất kho lưu trữ "
cp $ARCHIVEDIR/Python-$PYTHON_VERSION.tgz .
tar -xzf ./Python-$PYTHON_VERSION.tgz &> archive.log
cd ./Python-$PYTHON_VERSION
echo " cấu hình "
nếu [ "$x" = "tĩnh" ]
sau đó
./configure --prefix=$INSTALLDIR/$x --libdir=$INSTALLDIR/$x/lib &> configure.log
khác
xuất LD_RUN_PATH=$INSTALLDIR/$x/lib
./configure --enable-shared --prefix=$INSTALLDIR/$x --exec-prefix=$INSTALLDIR/$x --libdir=$INSTALLDIR/$x/lib &> configure.log
có
echo " xây dựng "
làm &> làm.log
echo "cài đặt"
thực hiện cài đặt &> make_install.log
echo " xong "
xong
### công cụ thiết lập
đối với x trong tĩnh động
LÀM
echo "Cài đặt setuptools ($x)"
đĩa $WORKDIR/$x
echo " trích xuất lưu trữ "
cp $ARCHIVEDIR/ez_setup-$EZ_SETUP_VERSION.tar.gz .
tar -xzf ./ez_setup-$EZ_SETUP_VERSION.tar.gz &> archive.log
cp $ARCHIVEDIR/setuptools-$SETUPTOOLS_VERSION.zip .
giải nén ./setuptools-$SETUPTOOLS_VERSION.zip &> archive.log
cp ./ez_setup-$EZ_SETUP_VERSION/ez_setup.py ./setuptools-$SETUPTOOLS_VERSION/.
cd ./setuptools-$SETUPTOOLS_VERSION
echo "cài đặt"
$INSTALLDIR/$x/bin/python ./ez_setup.py &> setup.log
echo " xong "
xong
Người Cython
đối với x trong tĩnh động
LÀM
echo "Cài đặt Cython ($x)"
đĩa $WORKDIR/$x
echo " trích xuất kho lưu trữ "
cp $ARCHIVEDIR/Cython-$CYTHON_VERSION.tar.gz .
tar -xzf ./Cython-$CYTHON_VERSION.tar.gz &> archive.log
đĩa ./Cython-$CYTHON_VERSION
echo "cài đặt"
$INSTALLDIR/$x/bin/python ./setup.py cài đặt &> install.log
echo " xong "
xong
NumPy
đối với x trong tĩnh động
LÀM
echo "Cài đặt NumPy ($x)"
đĩa $WORKDIR/$x
echo " trích xuất kho lưu trữ "
cp $ARCHIVEDIR/numpy-$NUMPY_VERSION.zip .
giải nén ./numpy-$NUMPY_VERSION.zip &> archive.log
đĩa ./numpy-$NUMPY_VERSION
echo " xây dựng "
$INSTALLDIR/$x/bin/python ./setup.py xây dựng --fcompiler=gfortran &> build.log
echo "cài đặt"
$INSTALLDIR/$x/bin/python ./setup.py cài đặt &> install.log
echo " xong "
xong
Khoa học
đối với x trong tĩnh động
LÀM
echo "Cài đặt SciPy ($x)"
đĩa $WORKDIR/$x
echo " trích xuất kho lưu trữ "
cp $ARCHIVEDIR/scipy-$SCIPY_VERSION.tar.gz .
tar -xzf ./scipy-$SCIPY_VERSION.tar.gz &> archive.log
đĩa ./scipy-$SCIPY_VERSION
echo " cấu hình "
echo "[MẶC ĐỊNH]" > ./site.cfg
echo "thư mục thư viện = $LAPACKDIR/lib64" >> ./site.cfg
echo "search_static_first = true" >> ./site.cfg
echo " xây dựng "
$INSTALLDIR/$x/bin/python ./setup.py xây dựng --fcompiler=gfortran &> build.log
echo "cài đặt"
$INSTALLDIR/$x/bin/python ./setup.py cài đặt &> install.log
echo " xong "
xong
### MatPlotLib
đối với x trong tĩnh động
LÀM
echo "Cài đặt MatPlotLib ($x)"
đĩa $WORKDIR/$x
echo " trích xuất kho lưu trữ "
cp $ARCHIVEDIR/matplotlib-$MATPLOTLIB_VERSION.tar.gz .
tar -xzf ./matplotlib-$MATPLOTLIB_VERSION.tar.gz &> archive.log
cd ./matplotlib-$MATPLOTLIB_VERSION
echo " xây dựng "
$INSTALLDIR/$x/bin/python ./setup.py xây dựng &> build.log
echo "cài đặt"
$INSTALLDIR/$x/bin/python ./setup.py cài đặt &> install.log
echo " xong "
xong
biên tập:Tôi đã xác định được nguyên nhân có thể gây ra vấn đề. Nếu tôi xóa khi cài đặt Python động xuất LD_RUN_PATH=$INSTALLDIR/$x/lib
Được rồi, mã nhúng của tôi hoạt động. Tôi đã in qua mã nhúng hệ thống.đường dẫn
, điều này cho biết cài đặt đã đúng. NHƯNG... Theo cách này, tôi không thể sử dụng cài đặt trực tiếp: nó tải phiên bản sai được tìm thấy trên hệ thống (khi tôi in hệ thống.đường dẫn
Tôi thấy nó trỏ tới /usr/...). Ngoài ra, tôi không muốn thiết lập các biến môi trường để khởi động Python vì tôi sử dụng nhiều phiên bản Python trên cùng một máy.
biên tập: Giữ nguyên tập lệnh cài đặt Python mặc định, tôi đã giải quyết vấn đề bằng cách thêm -rdynamic vào các tùy chọn khi biên dịch các ví dụ C++. Nhưng tôi không hiểu rõ lựa chọn này là gì và nó sẽ dẫn đến thảm họa gì...
Nếu tôi hiểu đúng thì bạn muốn chạy phiên bản được liên kết tĩnh trong khi cài đặt Python home thành phiên bản được liên kết động. Cách này không hiệu quả.
Điều sau đây xảy ra: Khi bạn chạy một thư viện được liên kết tĩnh Py_Khởi tạo()
Đến một lúc nào đó nó sẽ cố gắng nhập khẩu _địa phương
mô-đun. Bởi vì bạn thiết lập Python home để liên kết động phiên bản, nó sẽ tải $INSTALLDIR/dynamic/lib/python2.7/lib-dynload/_locale.so
. Thư viện này và $INSTALLDIR/động/lib/libpython2.7.so.1.0
Liên kết động. Bây giờ bạn có hai bản sao của trình thông dịch. Bản sao đầu tiên là bản sao được liên kết tĩnh, đang được khởi tạo. Bản sao thứ hai chưa được khởi tạo. Khi mô-đun động nhập máy móc cố gắng khởi tạo _địa phương
mô-đun, nó không thành công vì _địa phương
Hàm init của __init__ tham chiếu đến trình thông dịch thứ hai hoàn toàn chưa được khởi tạo.
Lý do gì khiến bạn cố gắng làm điều này? Nếu trước tiên bạn cho chúng tôi biết bạn đang cố gắng giải quyết vấn đề gì, chúng tôi có thể giúp bạn.
biên tập:(Tôi đã viết bài này sau lần chỉnh sửa đầu tiên và cho đến giờ tôi vẫn chưa thử -rdynamic
Điều gì xảy ra): Khi bạn không thiết lập Đường dẫn LD_RUN
giờ,$INSTALLDIR/dynamic/lib/python2.7/lib-dynload/_locale.so
Sẽ được liên kết động với hệ thống libpython2.7.so
. Lý do bạn không thấy lỗi là do bạn nhập _địa phương
Mô-đun này gặp lỗi ImportError (thay vì lỗi phân đoạn), nhưng lỗi ImportError này được phát hiện trong quá trình khởi tạo trình thông dịch (trong khi lỗi phân đoạn không thể phát hiện được trước đó). Tuy nhiên, nếu bạn thử nhập vào trình thông dịch nhúng _địa phương
(hoặc bất kỳ mô-đun mở rộng nào khác, chẳng hạn như _cấu trúc
), bạn sẽ nhận được lỗi sau:
Theo dõi (cuộc gọi gần đây nhất là cuộc gọi cuối cùng):
Tệp "", dòng 1, trong
ImportError: $INSTALLDIR/dynamic/lib/python2.7/lib-dynload/_locale.so: ký hiệu không xác định: PyUnicodeUCS2_FromObject
biên tập:Khi biên dịch theo phiên bản Python tĩnh Xin chào.cpp
Khi nào, thường là hầu hết các ký hiệu (chẳng hạn như _PyThreadState_Hiện tại
) không kết thúc bằng một bảng ký hiệu động. Đó là lý do tại sao bạn sẽ nhận được "hai bản sao của trình thông dịch" và lỗi phân đoạn như mô tả ở trên. Tuy nhiên, khi đi qua -rdynamic
, các ký hiệu này sẽ kết thúc trong bảng ký hiệu động, vì vậy bây giờ hàm init của mô-đun trong _locale.so được xây dựng "động" tham chiếu _PyThreadState_Hiện tại
Xây dựng "tĩnh". Tuy nhiên, tôi vẫn chưa tin rằng những gì bạn đang cố gắng thực hiện (sử dụng một chương trình được liên kết với bản dựng "tĩnh" với bản dựng "động" của trang chủ Python) là một ý tưởng hay. ;)
Tôi là một lập trình viên xuất sắc, rất giỏi!