2

I am working with the 3.6.4 source release of Python. I have no trouble building it with Visual Studio as a dynamic library (/MDd) I can link the Python .dll to my own code and verify its operation.

But when I build it (and my code) with (/MTd) it soon runs off the rails when I try to open a file with a Python program. A Debug assertion fails in read.cpp ("Expression: _osfile(fh) & FOPEN"). What I believe is happening is the Python .dll is linking with improper system libraries. What I can't figure out is how to get it to link with the correct ones (static libraries).

Jiminion
  • 5,080
  • 1
  • 31
  • 54
  • That's an assertion, not a `run off the rails`. It doesn't mean there are any link errors - you wouldn't be able to use either library if there were link errors, much less execute assertions in them. This means that the code is trying to read from a closed file *or* it's [using file functions on socket handles](https://stackoverflow.com/questions/4778043/winsock-not-supporting-read-write/12608707#12608707). In Windows sockets aren't files. What source are you trying to build? Have you check how the Python binaries for Windows are built? Something tells me they use different functions – Panagiotis Kanavos Jan 31 '18 at 15:14
  • My code works fine if built with /MDd. – Jiminion Jan 31 '18 at 15:25
  • And the [embeddable python.dll](https://www.python.org/downloads/release/python-364/) also works, and is available for download at python.org. What could have happened is that you linked against a library that uses file functions instead of socket functions. VS provides *far* better support for C++ than C - it's one of the best compilers for C++ while C was essentially abandoned until VS 2017. *Maybe* you'll have better luck with VS 2017. I'd check the build instructions for Windows first though. – Panagiotis Kanavos Jan 31 '18 at 15:35
  • A hint: "The solution has no configuration for static libraries. However it is easy to build a static library instead of a DLL. You simply have to set the "Configuration Type" to "Static Library (.lib)" and alter the preprocessor macro "Py_ENABLE_SHARED" to "Py_NO_ENABLE_SHARED". You may also have to change the "Runtime Library" from "Multi-threaded DLL (/MD)" to "Multi-threaded (/MT)". " – Jiminion Jan 31 '18 at 15:51

1 Answers1

4

This is what I needed to do to build and use python statically embedded in another application.

To build the static python library (e.g., python36_d.lib, python36.lib)

  1. Convert ALL projects in the python solution (pcbuild.sln) to static. This is about 40 projects, so it may take awhile. This includes setting library products to be build as 'static lib', and setting all /MD and /MDd build options to /MT and /MTd.

  2. For at least the pythoncore project alter the Preprocess define to be Py_NO_ENABLE_SHARED. This tells the project it will be looking for calls from static libraries.

  3. By hook or crook, find yourself a pyconfig.h file and put it in the Include area of your Python build. It is unclear how this file is built from Windows tools, but one seems to be able to snag one from other sources and it works ok. One could probably grab the pyconfig.h from the Pre-compiled version of the code you are building. [By the way, the Python I built was 3.6.5 and was built with Windows 2015, update 3.]

Hopefully, this should enable you to build both python36.lib and python36_d.lib. Now you need to make changes to your application project(s) to enable it to link with the python library. You need to do this:

  1. Add the Python Include directory to the General->Include Directories list.
  2. Add the Python Library directories to the General->Library Directories lists. This will be ..\PCBuild\win32 and ..\PCBuild\amd64.
  3. Add the define Py_NO_ENABLE_SHARED to the C/C++ -> Preprocessor area.
  4. For Linker->input add (for releases) python36.lib;shlwapi.lib;version.lib and (for debugs) python36_d.lib;shlwapi.lib;version.lib.

And that should be it. It should run and work. But one more thing. In order to be able to function, the executable needs to access the Lib directory of the python build. So a copy of that needs to be moved to wherever the executable (containing the embedded python) resides. Or you can add the Lib area to the execution PATH for windows. That should work as well.

That's about all of it.

Jiminion
  • 5,080
  • 1
  • 31
  • 54
  • 1
    There is a downside to all of this. The Python module system depends on dynamic libraries, so if you get this whole thing going, you won't be able to import modules that have a .dll associated with them that needs to be loaded. See: https://stackoverflow.com/questions/19560594/how-to-import-static-library-in-python – Jiminion Jul 24 '19 at 14:17
  • very true, however if the goal is to produce a standalone exe with no deps and no unpacking behavior, that is the main upside. You cannot do very much, you will have to disable site loading behavior, and cannot import much of anything. – smaudet Feb 08 '23 at 13:44
  • Also wanted to say that the project builds, pretty much only the libraries after conversion (very few if any of the exes work, even after adjusting to /MT(d)), and I got this working with python 3.10.1 – smaudet Feb 08 '23 at 13:46