Python in C++: Unresolved external - c++

I try to embed Python in my C++ application, but the linker keeps saying this error:
[ILINK32 Error] Error: Unresolved external '_PyModule_Create2TraceRefs' referenced from E:\CPP PROJECTS\ANDERLICHT\WIN32\DEBUG\ANDERLICHT.OBJ
I'm using Embarcadero C++ Builder XE2, so I converted the python33.lib with coff2omf.exe.
This is my code in main.cpp:
#include "anderlicht.c"
#pragma comment(lib, "python33_omf.lib")
// In main():
PyImport_AppendInittab("anderlicht",PyInit_anderlicht);
Py_SetProgramName(programName.w_str());
Py_Initialize();
In anderlicht.c the Python.h is included. What do I have to do to fix this error?

I had the same problem, but I found a solution that doesn't need rebuild.
If you are developing a new application, you are in debug mode: the compiler defines _DEBUG. In the file "pyconfig.h" (near line 336 for python 3.6.3) you can find:
#ifdef _DEBUG
#define Py_DEBUG
#endif
=> Remove this code.
If you leave that code,you are in Py_Debug mode, so in object.h triggers this:
#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)
#define Py_TRACE_REFS
#endif
That in modsupport.h defines this alias:
#ifdef Py_TRACE_REFS
/* When we are tracing reference counts, rename module creation functions so
modules compiled with incompatible settings will generate a
link-time error. */
#define PyModule_Create2 PyModule_Create2TraceRefs
#define PyModule_FromDefAndSpec2 PyModule_FromDefAndSpec2TraceRefs
#endif
So your compiler needs a custom version of Python.
Now enjoy your standard embedded python.

The problem is most likely that you're using different compiler flags in building your code than were used in building the Python DLL. In particular, PyModule_Create2TraceRefs is only defined if you have -DPy_TRACE_REFS (which usually passed in via EXTRA_CFLAGS in the make command on Unix; I have no idea how you do it with Embarcadero C++ Builder on Windows). Usually, this isn't defined—in particular, if you're using a DLL from a pre-build Python binary, it won't have it defined.
So, if you want to have custom flags in building your code, you need to rebuild Python itself with the same flags. Otherwise, you need to get the flags that were used to build Python, and use the same ones when building your code.
On Unix, this is trivial: Just call python3.3-config --cflags and python3.3-config --ldflags to get the flags to pass to your compile and link steps. On Windows, it's less trivial. The Building C and C++ Extensions on Windows chapter in the docs explains how to do it when you're using the same toolchain used to build Python itself (usually MSVC), and if you're using mingw with its MSVC-compat features there's documentation elsewhere on how to do that… but if you're using a different toolchain, you will need to figure some of it out yourself.

Related

Compiling artoolkitx-calibration for iOS: C-linkage specified, but returns user-defined type 'cv::Size' which is incompatible with C

I'd like to run the ARToolKitX Calibration app on iOS. Unfortunately, the app isn't available in the App Store, so I assume I'd have to compile it myself. Luckily, I have an active Apple Developer account...
So I got the source code from GitHub:
git clone https://github.com/artoolkitx/artoolkitx-calibration
cd artoolkitx-calibration
Then I downloaded the ARToolKitX iOS library from https://github.com/artoolkitx/artoolkitx/releases/download and I followed the steps in the iOS section of the build.sh script to link this SDK to the Xcode project.
I opened the project with Xcode 9.3 on macOS High Sierra 10.13.3.
I downloaded the opencv2.framework library from SourceForge and linked it: https://sourceforge.net/projects/opencvlibrary/files/opencv-ios/
Xcode reported an issue in line 61 of prefs.hpp:
cv::Size getPreferencesCalibrationPatternSize(void *preferences);
'getPreferencesCalibrationPatternSize' has C-linkage specified, but returns user-defined type 'cv::Size' (aka 'Size_') which is incompatible with C
Any pointer to get a step further in this compilation process would be greatly appreciated!
I just had the same problem today. You need to make sure that your source code files, usually the '.c' and the '.h' files, are interpreted as C++ headers and sources. For this specific error, trace back which file calls cv::Size and change its type to C++ header/source.
The compilation issue was fixed by removing the following lines around the error-generating usage of cv::Size:
#ifdef __cplusplus
extern "C" {
#endif
...
#ifdef __cplusplus
}
#endif

Building OpenSSL under Borland C++ Builder, Win 8.1

I'm following the instructions from INSTALL.W32 (various OpenSSL versions), in general it's:
* Configure for building with Borland Builder:
> perl Configure BC-32
* Create the appropriate makefile
> ms\do_nasm
* Build
> make -f ms\bcb.mak
Now, I do get two kind of errors when trying to build:
For OpenSSL < 1.0.0
nasmw -f obj -d__omf__ -ocrypto\md5\asm\m5_win32.obj .\crypto\md5\asm\m5_win32.asm
'nasmw' is not recognized as an internal or external command,
operable program or batch file.
Otherwise
Warning W8017 C:\CBuilder5\Include\sys/stat.h 34: Redefinition of 'S_IFMT' is not identical
Warning W8017 C:\CBuilder5\Include\sys/stat.h 35: Redefinition of 'S_IFDIR' is not identical
Error E2227 .\crypto\rand\randfile.c 226: Extra parameter in call to _open in function RAND_write_file
Warning W8053 .\crypto\rand\randfile.c 262: '_chmod(const signed char *,int,...)' is obsolete in function RAND_write_file
*** 1 errors in Compile ***
Yes, I feel bad for using Borland C++ Builder 5 but I can't do anything about it, and yes, I consider the Shining Light option if everything else fails.
I do not use OpenSSL but from your text some hints:
NASM
is not default assembler for Borland compilers
you need to download and install it first
(it is for free and one of the best compilers I used in the past)
you are missing some #define before including OpenSSL or including in wrong order
that is why you have the first warnings and most likely also the error
some libs need to add configuration #defines (added by some specific IDE's)
to specify what compiler,platform,endianess... is used
before any includes
usually if you include in wrong order then the defines are defined for some instances of a lib file but not for all
so try to reorder the includes
sometimes helps to include before the lib some other thing like conio,stdio,windows,...
to determine which define is missing or wrong open the stat.h
and look for #ifdef #ifndef statements around S_IFMT
The solution for the newest version (1.0.2d) was to:
remove the extra parameter from randfile (which, as comment stated, was unnecessary),
edit ms\bcb.mak, search for -DMD5_ASM -DSHA1_ASM -DRMD160_ASM
and change to -DMD5_NO_ASM -DSHA1_NO_ASM -DRMD160_NO_ASM . (there was an unresolved external error with SHA, MD5 and RMD160, they basically couldn't be compiled in asm).
There were some other steps included as well, but they're just specific to my environment.

How to use standard library with Clang and LibTooling

I want to use Clang and LibTooling to create some C++ source analysis and transformation tools. I've built Clang and LibTooling following this tutorial, and I've been able to run and create some analysis tools and compile C++ programs using the Clang binary I built. However, if I include headers from the standard library (in either source files or my tools), I run into issues when compiling or running the source files/tools. For instance, if I run clang-check on the following C++ source file:
#include <iostream>
int main() {
std::cout << "Hello";
return 0;
}
I get "fatal error: 'iostream' file not found". (Note: I can compile C++ programs, e.g. ones with user-defined classes, just not C++ programs using the standard library.) In an attempt to resolve the issue, I built libc++ (following this guide, building it in the llvm/project directory where I built LLVM and Clang), but I'm still having trouble getting Clang and the tools to use libc++. Now, if I try to compile a test file using:
export CPLUS_INCLUDE_PATH="~/clang-llvm/llvm/projects/libcxx/include"
export LD_LIBRARY_PATH="~/clang-llvm/llvm/projects/libcxx/lib"
~/clang-llvm/llvm/build/bin/clang++ ~/Documents/main.cpp
Then I get "fatal error: 'unistd.h' file not found". So my question is this: how do I properly point Clang and my tools to use libc++?
I am running OS X Yosemite 10.10 and using Clang 3.6.0.
Clang comes with some custom includes. So usually you have clang in
/usr/bin/clang++
and the includes in
/usr/lib/clang/3.6.1/include
but clang looks for them as a relative path:
../lib/clang/3.6.1/include
so make sure this relative path is accessible from either the clang++ binary, or your libtooling application.
Include your tool into this:
#include "clang/Tooling/CommonOptionsParser.h" // For reading compiler switches from the command line
#include "clang/Tooling/Tooling.h"
static cl::OptionCategory MyToolCategory("SearchGlobalSymbols");
static cl::extrahelp MoreHelp("\nMore help text..."); // Text that will be appended to the help text. You can leave out this line.
/* Your code (definition of your custom RecursiveASTVisitor and ASTConsumer) */
/* Define class MyASTFrontendAction here, derived from ASTFrontendAction */
int main(int argc, const char **argv)
{
/* Your code */
CommonOptionsParser op(argc, argv, MyToolCategory); // Parse the command-line arguments
ClangTool Tool(op.getCompilations(), op.getSourcePathList()); // Create a new Clang Tool instance (a LibTooling environment)
return Tool.run(newFrontendActionFactory<MyASTFrontendAction>().get()); // Run custom Frontendaction
}
The CommonOptionsParser allows you to read commands from the command line that are passed to the compiler.
For example, you can now call your tool like this:
your-tool yoursourcefile.c -- -nostdinc -I"path/to/your/standardlibrary"
Everything after the double dash will be passed to the compiler. Possible flags are described here:
http://clang.llvm.org/docs/CommandGuide/clang.html
-nostdinc tells the Preprocessor not to look for standard include paths. You can specify you own paths instead after -I.
Hope it helped someone :) Ask me if I wasn't specific enough.
Did you move/rename any of the parent directories after building/installing? The compiler should have been configured to know where to look for its standard libraries without having to specify the environment variable paths.
Use homebrew and install llvm using the command
brew install llvm
Your problem should be solved.

How to export a global variables/arrays from the dll built using VS compiler to the client built using MingW compiler?

General info [optional]:
I have recently acquantied with static & dynamic libraries.
Now I am trying to learn how to use DLLs, I try to immitate all possible variants of usage in order to encounter possible bottlenecks and methods to prevent them.
My goal:
Is to find out how to export a global variable from a DLL which was compiled with one compiler for ex. VS compiler (IDE Visual studio 2010) to the client which was compiled using another compiler MingW(IDE Qt Creator 5.0). Actually I am interested in specific case, not common, but if info for common case will be provided - it will be great.
Also important that connection of the dll to the client is implicit(not expilcit then we manually connect library).
Also I have posed such question because it is interesting for me how to support a client`s application by providing updated dll, because version of compiler used for client and dll at the beggining of a project can be the same, but as time passes by they may vary, so how to solve this binary compatibility issue?
I got stuck trying to export an array defined in dll to the client.
DLL & Client
/* header file. Is used by both: dll and client */
#ifdef EXPORT
#define MYLIB __declspec(dllexport)
#else
#define MYLIB __declspec(dllimport)
#endif
extern "C" { // My be this directive not supported by MingW???
#ifdef VS2010
extern MYLIB char ImplicitDLLName[];
#else
Q_DECL_IMPORT extern char ImplicitDLLName[];
#endif
}
DLL
/* .cpp file in dll: */
#define EXPORT ""
#define VS2010 ""
char ImplicitDLLName[] = "MySUMoperator";
Client
/* Client .cpp */
void MainWindow::on_pushButtonAdd_clicked()
{
// ...
printf("%s",ImplicitDLLName);
}
Attempt to use the array in the Client results in the following error raised by the linker:
error: undefined reference to `_imp__ImplicitDLLName'
I am aware of names mangling and compatibilty issue that may arise from that, but I am trying to resolve it by disabeling it using
extern "C"{}
By the error returned from the clients linker I can tell that I have failed to disable it, because it reports that reference on _imp__ImplicitDLLName wasnt found, so I guess that it is ImplicitDLLName only decorated with additional symobls(name mangling).
I wonder may be this issue arose due to different implementation of arrays in different compilers or alignment of arrays in memory??
Question: how to solve this binary comptability issue??

Defining _LIBC in C++ Program

Some of the GNU library code can be have enhanced debugging if the flag _LIBC is set. While using -D_LIBC when compiling gives the error message
"/usr/include/gnu/stubs.h:7:3: #error Applications may not define the macro _LIBC"
So how do you define this variable?
You'd define it when compiling LibC. It's Open Source, after all.