嵌入python和XCode:如何设置相对python搜索路径和定位系统模块

时间:2016-06-08 17:23:15

标签: xcode python-2.7

我在Mac OS X El Capitan 10.11.4上使用XCode进行开发。我的项目混合了C,C ++ 11和嵌入式Python。

我的项目正常工作,因为我可以调用Python脚本并通过嵌入python将数据返回到C ++。在我的项目中,我使用绝对路径作为pythons搜索路径从'C'加载脚本。

XCode project/
-- Python.framework/
-- python/
---- mypython.py
-- python_interface.c
-- main.cpp

我的问题是:

Q1:我已经提供了Python,但是从XCode中看不出来,而是系统提供的是。这不是现在的问题,但我最终想知道如何指出我选择的装置。

我已将brew.Python文件捆绑到我的项目中,以便成功链接。我知道它不会调用它,因为如果我错误地指定我的模块路径,它会抱怨系统python无法找到它。另外,'system(which python)'报告'/ usr / bin / python'。

Q2:如何在XCode中指定python的相对搜索路径,即从我的项目中的“C”代码中找到我的本地python模块?

Q3:如何在运行时确定python'requests'安装的绝对路径?我的python模块导入了它,它可能与我指定的不同。

目前,我使用Py_GetPath和Py_SetPath来指示这些使用绝对路径,即“/usr/local/lib/python2.7/site-packages”用于“请求”。

我知道如何在python本身(Find path of module without importing in Python)中找到模块路径,但这不是我想要做的。我需要知道脚本运行之前的路径。

如上所述,我正在嵌入python,所以我正在从'C'调用我的python脚本(参见https://docs.python.org/2/extending/embedding.html?highlight=embedded#pure-embedding)。

我找到了以下链接,展示了如何获取可执行文件的路径。我想要的是项目的路径,并使用相对路径来定位我的python模块。

Relative Paths Not Working in Xcode C++

Programmatically retrieving the absolute path of an OS X command-line app

我找到了这个帖子; Relative imports for the billionth time。我从'C'代码到我的python脚本的搜索路径是相对的,但我相信这篇文章主要是关于相互导入其他模块的python脚本。

问题4:将Frameworks添加或链接到XCode项目的结果是相同的。在我的例子中,Python.framework出现在“项目导航器”中,它被添加到“链接二进制文件库”部分。然而,以下两篇文章表明两者之间存在差异。它不是可执行文件的大小,因为我尝试了两种方法,但这仍然是相同的。

https://developer.apple.com/library/ios/recipes/xcode_help-structure_navigator/articles/Adding_a_Framework.html

这表明了;

  

“您以这种方式添加的框架是包含框架的目标代码和运行时资源的第三方构建的包。有关链接到框架而不将其添加到项目中的信息,请参阅相关文章。”

并包含指向“链接到库或框架”的链接,其网址似乎与此相矛盾(AddingaLibrarytoaTarget)。

https://developer.apple.com/library/ios/recipes/xcode_help-project_editor/Articles/AddingaLibrarytoaTarget.html#//apple_ref/doc/uid/TP40010155-CH17

感谢。

1 个答案:

答案 0 :(得分:0)

我的问题的一些答案

我重新组织了我的项目,并在谷歌上使用各种来源创建了我自己的Makefile。这是因为我想要移植我的项目,因为我无法回答上述问题。几年前我和Makefiles合作过,但我对XCode来说比较新。

要创建我的Makefile,这些是我使用的资源;

下一步是自动化生成Makefile的过程;

新的Makefile项目结构

project/
-- Debug/ or Release/ 
-- Makefile
-- obj/
---- target .o files
-- python/
---- .py files
-- src/
---- C/C++ files incl headers

生成文件

# https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables
# $@ Contains the target file name.
# $< Contains the first dependency file name.
# $^ The names of all the prerequisites, with spaces between them.

# Produces a Release build by default, or Debug build with ‘make debug’

EXEC = $(BUILD_DIR)/my_exe_name

CCFLAGS=-c -Wall
CXXFLAGS=-c -Wall -std=c++11
BINARY_DIR=Obj
BUILD_DIR=Release

PYTHON_CCFLAGS=$(shell python2.7-config --cflags)
PYTHON_LDFLAGS=$(shell python2.7-config --ldflags)

CPP_FILES := $(wildcard src/*.cpp)
C_FILES := $(wildcard src/*.c)

CPP_OBJ_FILES := $(addprefix $(BINARY_DIR)/,$(notdir $(CPP_FILES:.cpp=.o)))
C_OBJ_FILES := $(addprefix $(BINARY_DIR)/,$(notdir $(C_FILES:.c=.o)))

C_HEADERS = $(filter-out $(addsuffix .h, $(basename $(SOURCE_FILES))), $(wildcard src/*.h))
CPP_HEADERS = $(filter-out $(addsuffix .h, $(basename $(SOURCE_FILES))), $(wildcard src/*.hpp))

### Take the BUILD_DIR as a dependency but ignore it’s timestamp
### as it will change whenever something is written into it

$(EXEC): $(C_OBJ_FILES) $(CPP_OBJ_FILES) | ${BUILD_DIR}
    @echo [ $(EXEC) ]
    $(CXX) $(LD_FLAGS) $(PYTHON_LDFLAGS) -o $(EXEC) $^

### The objects in the BINARY_DIR folder require the BINARY_DIR to be created
### as well as any changes to the other dependencies

$(BINARY_DIR)/%.o: src/%.cpp $(CPP_HEADERS) $(C_HEADERS) | ${BINARY_DIR}
    @echo [ make $@ ]
    $(CXX) $(CXXFLAGS) $(C11_FLAGS) -o $@ $<

$(BINARY_DIR)/%.o: src/%.c $(C_HEADERS) | ${BINARY_DIR}
    @echo [ make $@ ]
    $(CC) $(CCFLAGS) $(PYTHON_CCFLAGS) -o $@ $<

${BINARY_DIR}:
    mkdir $(BINARY_DIR)

$(BUILD_DIR):
    mkdir $(BUILD_DIR)

### clean the targets. We can have either Debug or Release but I don’t know
### how to specify either in one line, i.e. we don’t want to do ‘make clean debug’
### to specify the Debug folder

.PHONY: clean cleanmsg cleanrel cleandeb

clean: cleanmsg cleanrel cleandeb
    rm -r -f $(BINARY_DIR)

cleanmsg:
    @echo Cleaning product and all .o files

cleanrel:
    rm -r -f Release

cleandeb:
    rm -r -f Debug

# Debug build
# Ensure these are last. I had them below the original decl of the flags
# and they were always set! Now you have to ‘make debug’ for it to take effect

.PHONY: debug
debug: CCFLAGS += -DDEBUG -g
debug: CXXFLAGS += -DDEBUG -g
debug: BUILD_DIR=Debug
debug: $(EXEC)

将XCode与新的Makefile项目一起使用

要继续使用XCode开发我的项目,我在Makefile项目上创建了一个XCode项目。见http://hiltmon.com/blog/2015/08/01/simple-c-plus-plus-from-makefiles-to-xcode-builds/

的答案

通过这样做,我能够在某种程度上回答上述问题。 Q3 仍未得到答复。

A1:创建一个Makefile项目,并在其中声明平台指定的python安装。这样您就不需要将其捆绑到XCode项目中。

请参阅https://docs.python.org/2/extending/embedding.html?highlight=embedded#compiling-and-linking-under-unix-like-systems

A2:使XCode项目相对,以便您的产品驻留在项目中。如果您希望在/ usr / local / bin中安装exe,则不是最佳答案。

请参阅How to change output directory for a target(gp_coder的回答)。

我的Makefile将exe存储在./Release/(make)或./Debug/(make debug)中。 XCode也是如此,但是具有不同的几个级别的前导目录。要更改此设置,只需指定当前目录'。'在XCode的目标“项目设置&gt;高级&gt;自定义&gt;产品”目标目录中,这将匹配Makefile。

我的python搜索路径设置为

  

:../蟒:/usr/local/lib/python2.7/site-packages

'../'因为我的exe在./Debug或./Release和python /是相对的。

  

但是,如果你从cmdline调用exe,那么一个目录就无法工作了。例如./Release/my_exe_name。这是因为它采用当前目录并使用与之相关的搜索路径。

     

存储和设置绝对路径会更好。见Where to store application data (non-user specific) on Linux

在我意识到答案之前,我发了一个问题; How to set relative project path in XCode when target is /usr/local/bin

第二个路径是我的python请求目录。 Q3 指的是这个。

A3: 不知道。仍需要解决如何在运行时将我已安装的python模块路径传递到我的C代码之前调用python,因为这样做我的python搜索路径。此值会根据您的安装而更改。

A4:这不是一个问题,而是一个混乱。在Makefile中指定它以避免捆绑。