2012-11-28 16 views
1

我想看看是否有人尝试过这样的事情,并得到一些建议是否追求这个想法。我有一个Python脚本,我想创建一个DLL。在做了一些研究之后,执行此任务的最佳方法是将Python脚本嵌入到C中,然后从C代码生成一个dll。使用埃尔默生成C代码,然后创建DLL

然后我发现Elmer Software Glue:http://elmer.sourceforge.net/index.html,它将一个Python模块嵌入到C中。我想我可以使用Elmer将我的Python代码嵌入到C中,然后从那里创建一个dll。

我有人会给我一些保证,这可以工作,如果不是也许一些替代品。我愿意接受任何和所有建议。

回答

1

不知道你是如何解决问题的,但是我能够在Windows 7 x64上使用Elmer与Python 2.7.8和Elmer 1.1.7a创建DLL,我会分享我的经验。

我编译/编译环境中使用VisualStudio2005 NMAKE

我一路上遇到许多问题,特别是涉及到-frozen国旗和我的大版本的Visual Studio,但我得到什么似乎是现在工作的DLL。

我顶层笔记:

  • 我只好用静态链接MSVCRT80埃尔默因加载DLL与python27.dll包括MSVCRT90时发生冲突。
  • 图书馆,elmer.lib,需要在链接步骤,但只有在c存在:\埃尔默的\ src \建立\ temp.win32-2.7 \发布\埃尔默目录,现在看来似乎应该得到某处复制在名称中没有temp这个词,但是我设置了我的makefile以使用它从临时目录中。
  • 当使用-frozen时,可能会有数十个生成的.c文件
  • PyImport_FrozenModules和Py_FrozenFlag已由其他包含文件(pydebug)声明。
  • PyImport_FrozenModules正在重新定义(由于elPythonToC),而不是仅仅分配。
  • DL_IMPORT(在elPythonToC.py中使用)已弃用http://bugs.python.org/issue566100。应该使用PyApi_DATA代替我的想法,但没有真正的区别。 编辑不重要,因为我删除整个块,因为它正在重新定义PyImport_FrozenModules
  • 最后,我不得不包括python27.dll,elmer.dll。我相信MSVCRT90.dll还需要通过在目标机器上的MS再分发安装程序安装为python27.dll需要这一点。如果使用冷冻会得到我们一个分配这将是很好,但我会采取什么我可以得到的。
  • 我能有关python 2.6.5稍作修改运行该过程(例如,蟒路径为c:\ python26而不是C:\ python27)。
  • 测试脚本在python第一,埃尔默会很乐意包包含畸形的Python脚本。
  • 要创建一个调试的DLL,添加/Z7 /Od到CFLAGS和/incremental:no /debug到LINKFLAGS
  • 将是很好,如果某种在Python代码本身的格式化的评论或功能可以替代.elm文件。

现在,这里有详细的步骤我做了(不保证任何这些都是正确的,他们肯定不是最优的,但他们似乎为我工作):

  • 安装埃尔默
    • 下载并解压埃尔默某个目录(我选C:\埃尔默,所以我会用在整个我的例子)
    • 当我开始,我用的是2.7.2,我就遇到了这个问题:Compiling with cython and mingw produces gcc: error: unrecognized command line option '-mno-cygwin' 。我修补了Lib/distutils/cygwinccompiler.py以删除-mno-cygwin并将其安装,但我后来安装了2.7.8,我认为这可以解决潜在的问题。
    • 我想Elmer.dll静态链接到MSVCRT垃圾,因为我有一个旧版本的MSVCRT,所以我修改setup.py如下。 (我知道我不应该静态链接,你可能不希望这样,但如果你这样做:
    • 添加extraCompileArgs = []extraLinkArgs = []libDirs = []声明
    • 在Windows的特定构建选项,如果块添加:extraCompileArgs = ['/MT']extraLinkArgs = ['/MANIFEST']
    • libraries=libs后内部Setup(..., ext_modules=[Extension(
    • 添加, extra_compile_args=extraCompileArgs, extra_link_args=extraLinkArgs从命令提示,运行C:\埃尔默\ SRC>蟒的setup.py建立
    • 从命令提示,运行C:\埃尔默\ SRC>蟒setup.py安装
  • 修改的.py和适合我的需要.elm文件 - 这是比较容易的部分
  • 获取makefrozen.py makefrozen由埃尔默使用-frozen选项时使用,但它似乎并没有被列入标准的win32 MSI发行版。
    • makefrozen被包括在蟒蛇的源代码,但不包括在Windows MSI安装程序,那么请从www.python.org
    • 提取物\工具的源码包\冻结\到c:\ python27 \工具\冻结
  • 修改buildAndRun
    • 变化ELMERDIR到C:\
    • 路径应指向SET PATH=%PATH%;%ELMERDIR%;%THISDIR%
    • 设置ELMERDIR到C:\埃尔默\
  • 更新制作文件为我的配置工作(示例文件根本不与NMAKE或冻结的工作)。这里是我的生成文件,可以使用NMAKE构建冷冻或非冻结版本:

    PYTHONDIR=C:\Python27 
        ELMERDIR=C:\elmer 
        ELMERLIBDIR=$(ELMERDIR)\src\build\temp.win32-2.7\Release\elmer 
        ELMER_OUTPUT_DIR=Generated 
    
        CC=cl 
        RM=del /F /Q 
        ELMER=$(ELMERDIR)\elmer 
        shell=call 
    
        CFLAGS=/TC /LD 
        INCLUDEFLAGS=/I$(ELMER_OUTPUT_DIR) /I$(PYTHONDIR)\include /I$(PYTHONDIR)\Lib\site-packages\elmer 
        LINKFLAGS=/LIBPATH:$(PYTHONDIR)\libs python27.lib /LIBPATH:$(ELMERLIBDIR) elmer.lib 
    
        .PHONY: generatedFiles generatedFrozen all allFrozen 
        SRCS = Generated\*.c 
        OBS = $(SRCS:.c=.obj) 
    
        {Generated}.c{Generated}.obj:: 
         @echo Compiling... 
         @$(CC) /nologo $(CFLAGS) $(INCLUDEFLAGS) /c /FoGenerated\ $< 
    
        generatedFrozen: 
         echo Elmering 
         @$(shell) $(ELMER) -c -frozen -o $(ELMER_OUTPUT_DIR) -int MyDll.elm MyDll.py 
    
        generatedFiles: 
         echo Elmering 
         @$(shell) $(ELMER) -c -o $(ELMER_OUTPUT_DIR) -int MyDll.elm MyDll.py 
    
        showIncludeAndLinkFlags: 
         @echo includeDirs: 
         @$(shell) $(ELMER) --printIncludeFlags 
         @echo linkDirs: 
         @$(shell) $(ELMER) --printLinkFlags 
    
        MyDll.dll: $(OBS) 
         @echo Linking... 
         @Link $(LINKFLAGS) /DLL $(OBS) 
    
        all: 
         @echo "Making All" 
         @nmake generatedFiles 
         @nmake showIncludeAndLinkFlags 
         @nmake MyDll.dll 
    
        allFrozen: 
         @echo "Making All" 
         @nmake generatedFrozen 
         @nmake showIncludeAndLinkFlags 
         @nmake MyDll.dll 
    
        clean: 
         @echo cleaning 
         $(RM) .\Generated\*.* 2>nul || echo eatFailure >nul 
    
  • 调用NMAKE之前创建一个BUILD.BAT设置Visual Studio环境。这里是我的构建批处理文件的内容:

    @ECHO OFF 
        SETLOCAL 
        SET THISDIR=%~dp0 
        REM Setup Visual Studio build environment 
        REM Microsoft Visual Studio 8 == Visual Studio 2005 
        CALL "C:\Program Files (x86)\Microsoft Visual Studio 8\VC\vcvarsall.bat" 
        nmake clean 
        nmake allFrozen 
        pause 
        ENDLOCAL 
    
  • 修复编译/链接错误,它变得有点难看这里我不得不修改埃尔默代码来得到它的工作
    • 删除重复的声明和重新定义为Py_FrozenFlag和PyImport_FrozenModules
      • 打开C:\ python27 \ LIB \站点包\埃尔默\ elPythonToC.py文本或Python编辑
      • 删除或注释掉含0123的if(frozenFlag) :块和retCode += "DL_IMPORT(struct _frozen *) PyImport_FrozenModules;\n"(围绕线145)
      • 添加行:retCode += " PyImport_FrozenModules = _PyImport_FrozenModules;\n"含有线以上retCode += " retRunVal = PyImport_ImportFrozenModule((char*)\"%s\");\n"(围绕线189)
  • 复制DLL来分发文件夹
    • 复印MYDLL.DLL来自包含.elm文件的工作目录。从C:\ elmer \ src \ build \ lib.win32-2.6 \ elmer复制elmer.dll。从C:\ Windows \ SysWOW64复制python27.dll。
    • 必要时目标机上(或者只是找到MSVCRT90.dll在窗口并排侧配置和东西,旁边的DLL。看到http://msdn.microsoft.com/en-us/library/vstudio/ms235299.aspx安装Visual C++再发行组件包。

编辑 当我加了一些肉到我的DLL,我注意到冷冻进口的东西而不能正常工作,并导致我的DLL退出。我原来的修改是造成Py_FrozenFlag和PyImport_FrozenModules由当地确定,这引起PyImpor t_ImportFrozenModule在生成的c代码中失败。我已经对makefile进行了修改,以消除Py_NO_ENABLE_SHARED定义,删除了这些变量的定义和声明,将PyImport_FrozenModules的定义更改为赋值,现在一切似乎都正常工作。我已经成功连接到并从简单的C++应用程序调试我的dll。