Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trouble linking #2

Open
jamesd256 opened this issue Apr 9, 2016 · 12 comments
Open

Trouble linking #2

jamesd256 opened this issue Apr 9, 2016 · 12 comments

Comments

@jamesd256
Copy link

Hi,

I am testing out your statically compiled interpreter, and it seems to build fine.

I have a test project I'm using to see if I can link to it, and I have this compilation error:

Error 1 error LNK2019: unresolved external symbol __imp__Py_Initialize referenced in function _main static_python_test.obj static_python_test_2

Running dumpbin /all on my generated pythonembed.lib shows that the expected symbols are there:

B297C2 _Py_Initialize

But I don't understand why the linker is looking for __imp__Py_Initialize and not _Py_Initialize.

Are you able to point me in the right direction please?

Thanks,

James

@zeha
Copy link
Owner

zeha commented Apr 11, 2016

It may be necessary to compile your code with the macro Py_BUILD_CORE defined, so pyconfig.h does not mark Py_Initialize as a dllimport.

@jamesd256
Copy link
Author

In fact since posting, I tried with Py_NO_ENABLE_SHARED defined, and got past the __imp prefix thing.

I also found the blog post you did about this with the extra flags, so switched from building my project in VS 2015 to the command line environment. I actually tried both from the 7.1 SDK and from the VS2015 developer prompt with different resutls.

I will continue to research the issues below. I understand it is a fairly old project but it would be great to resurrect it. If you did happen to have an old sample projects you could share that builds successfully against the static lib, I would be very grateful.

Here is my make file based on your flags:

PYTHON_V=2.7.3
OPENSSL_V=1.0.1c
ROOT=..\\

CFLAGS=/c /GF /MP4 /nologo /EHsc /I$(ROOT)openssl-$(OPENSSL_V)\inc32 \
    /I$(ROOT)Python-$(PYTHON_V)\Include /I$(ROOT)Python-$(PYTHON_V)\PC \
    /DPy_BUILD_CORE /MD /W4 /O2
LINKFLAGS=/MACHINE:X86 /RELEASE /LTCG
LIBS=$(ROOT)openssl-$(OPENSSL_V)\out32\libeay32.lib \
    $(ROOT)openssl-$(OPENSSL_V)\out32\ssleay32.lib \
    $(ROOT)Python-$(PYTHON_V)\PCbuild\pythonembed.lib ws2_32.lib
CC= cl
LINK= link

all: simple.exe 

simple.obj:
  $(CC) $(CFLAGS) simple.c

simple.exe: simple.obj
  $(LINK) $(LINKFLAGS) -out:simple.exe simple.obj $(LIBS)

The code is very simple:

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

int main()
{
Py_Initialize();
return 0;
}

A sample of some link issues.

7.1 SDK:

MSVCRT.lib(MSVCR100.dll) : error LNK2005: _abort already defined in LIBCMT.lib(abort.obj)
pythonembed.lib(unicodeobject.obj) : error LNK2001: unresolved external symbol __imp__CharPrevA@8
libeay32.lib(cryptlib.obj) : error LNK2001: unresolved external symbol __imp__GetUserObjectInformationW@20

VS 2015 Dev env:

pythonembed.lib(pythonrun.obj) : error LNK2001: unresolved external symbol __imp__sprintf
OLDNAMES.lib(execve.obi) : error LNK2001: unresolved external symbol __imp__execve
libeay32.lib(cryptlib.obj) : error LNK2001: unresolved external symbol __imp__GetUserObjectInformationW@20

@zeha
Copy link
Owner

zeha commented Apr 12, 2016

I think the "already defined" error points to the python.lib and your code not being compiled with the same flags or compiler. Especially the /MT or /MD switches have to match in both builds.

@jamesd256
Copy link
Author

I have managed to build the executable now.

Thanks for your help with this Christian. Actually required me to just get my head down and learn how it all works. It wasn't those switches in fact, but some changes to my Makefile did it for me. Had to include the extra libraries shown below and change the nodefaultlib switch:

PYTHON_V=2.7.3
OPENSSL_V=1.0.1c
ROOT=..\\

CFLAGS=/c /GF /MP4 /nologo /EHsc /I$(ROOT)openssl-$(OPENSSL_V)\inc32 \
    /I$(ROOT)Python-$(PYTHON_V)\Include /I$(ROOT)Python-$(PYTHON_V)\PC \
    /DPy_BUILD_CORE /MD /W4 /O2
LINKFLAGS=/MACHINE:X86 /RELEASE /LTCG /NODEFAULTLIB:LIBCMT
LIBS=$(ROOT)openssl-$(OPENSSL_V)\out32\libeay32.lib \
    $(ROOT)openssl-$(OPENSSL_V)\out32\ssleay32.lib \
    $(ROOT)Python-$(PYTHON_V)\PCbuild\pythonembed.lib ws2_32.lib msvcrt.lib user32.lib shell32.lib advapi32.lib oleaut32.lib Gdi32.Lib Ole32.lib
CC= cl
LINK= link

all: simple.exe 

simple.obj:
  $(CC) $(CFLAGS) simple.c

simple.exe: simple.obj
  $(LINK) $(LINKFLAGS) -out:simple.exe simple.obj $(LIBS)

Incidentally, to get the initial lib built on Windows 10, some modifications of the process in your README were necessary. I didn't mention this before, but now I have a build it might help someone else get there:

Windows 10 Notes:

  • To install the 7.1 SDK with the full MSBuild tools, it is necessary to alter all locations in the registry
    (8, not the 2 reported, need to search) where the version of the installed .NET software is recorded:

http://stackoverflow.com/questions/32091593/cannot-install-windows-sdk-7-1-on-windows-10

  • GNU patch doesn't work. Triggers UAC and loads in a new console, doing nothing. Instead use Cygwin's patch and
    put the Cygwin bin folder where it's located in the path.

  • Neither versions of 7zip downloaded came with a 7za.exe, so it was necessary to rename 7z.exe to 7za.exe

  • nasm didn't install in the path supposed by the above path update. Instead use :

    SET PATH=C:\Program Files\7-Zip;C:\Users\james\AppData\Local\nasm;%PATH%

@jamesd256
Copy link
Author

I have now started to try to get your examples/embed.c working, and have made some progress, but I am stuck with this:

error LNK2001: unresolved external symbol _initcustomimport

I can't find any reference to that function. In fact, if you google it, it leads you back to this project as the only result. Did I misunderstand this example? Should it be possible to compile it without any extra resources?

@zeha
Copy link
Owner

zeha commented Apr 13, 2016

No, if you don't have a custom importer ready, you can just delete lines 19-40 in the example. Sorry about the confusion!

@jamesd256
Copy link
Author

I am sure it would have been obvious if I had really studied the code, but I am new to c and Python, so looking for as many clues as I can get.

My interest in your sample code is that it seems I could use it towards my goal, which is to create an standalone executable containing a specific package I have. This package calls for numpy and scipy, so I was hoping that using the direction in your example, I could perhaps call these two libraries at runtime rather than trying to statically build them into pythonembed.lib, which I know will be hard.

@zeha
Copy link
Owner

zeha commented Apr 13, 2016

Well, writing a custom importer without knowing details about Python and it's C API will be hard - but doable!

Linking numpy and scipy statically will probably be a similar effort to what I did in the project here.

@jamesd256
Copy link
Author

Ok. But do I actually need to write a custom importer. Can I not just
invoke the built in importation mechanics?

I am happy to bundle the external ready made libraries, so it isn't
necessary to go the static route if it is avoidable.
On 13 Apr 2016 09:45, "Christian Hofstaedtler" [email protected]
wrote:

Well, writing a custom importer without knowing details about Python and
it's C API will be hard - but doable!

Linking numpy and scipy statically will probably be a similar effort to
what I did in the project here.


You are receiving this because you authored the thread.
Reply to this email directly or view it on GitHub
#2 (comment)

@zeha
Copy link
Owner

zeha commented Apr 13, 2016

You need a custom importer if you want to ship a single binary file, which can not rely on external files -- by default, even the static python lib will load (pure) Python modules (resembling the standard library) from an external folder.
If you want to replace that, you need a custom importer. As hinted in the example, Python's zipimporter can be used as a starting point for such an importer.

@jamesd256
Copy link
Author

Very grateful for your engagement on this Christian.

Let me make it clear, as I mentioned, I am happy to rely on external files. I do not need to ship a single binary.

What I want is to build some stuff, or to be precise, my stuff into the binary. Public stuff like numpy and scipy I don't mind if my new Python calls these externally as normal Python would. In fact it's better.

@jamesd256
Copy link
Author

I see what you mean, you can't have a statically linked python load c extensions.

So as you say I'll have to try to build Numpy and Scipy statically. Wish me luck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants