Unresolved external symbol error when creating Armadillo DLL - visual-c++

I am trying to create a dynamic library of the Armadillo linear algebra library, which is originally a header-only library, using VC++ 2010 on Win XP. I created a new project, added the source files, and created a .def file specifying to export only one Armadillo function (the Col class), and I get the LNK2001 error for the Col class. I can create a main and use Col just fine, so I think Col is being included correctly.
I have also tried using "__declspec(dllexport)" on the function definition and it compiles, but the function is not exported since using dumpbin shows nothing, and I can not use the .dll sucessfully. Am I missing something here?

As Armadillo is a C++ template library that uses expression templates, I don't think it's possible to create a DLL out of it.
The expression templates are executed (run) at compile-time by the C++ compiler, whenever compiling code that uses Armadillo classes. Whenever a C++ library uses expression templates (part of template metaprogramming), the library can be thought of as an extension to the C++ compiler.
All the Armadillo code is in headers. As such, even if you managed to export one of the classes (eg. the Col class), none of the associated mathematical machinery (eg. addition, multiplication, etc) would be exported, which is defined all throughout the other parts of the library.

Related

Is it possible to use C++Builder and CMake to create Python modules?

C++Builder's 32-bit compiler, bcc32, by default creates shared libraries using the cdecl calling convention, prefixing exported functions with an underscore,
e.g. '_functionName'. Visual studio, on the other hand, don't prefix exported functions.
Python, when importing a pyd module, expects a function named PyInitialize_modulename. Since bcc32 prefix this function with an underscore, rendering it to be _PyInitialize_modulename, Python will not be able to import a bcc32 created module.
Using CMake, does anyone know how to add a module definition file, .def, to alias the prefixed function, to an 'unprefixed' one, when compiling/creating the pyd module?
Update. In response to Mr. Lebeau's answer below (as a comment);
This question is not about CTypes, but SWIG. CTypes allows for a simple way to wrap a C/C++ DLL, but mainly deals with C structures and POD data.
Swig, on the other hand, allows a client to get object oriented objects in Python, analogous to the ones exported from a C++ DLL. Swig can do this as it process C++ headers.
Swig does create a C++ file that is compiled into a .pyd file (in essence a DLL as noted). The first exported function that Python looks for when trying to load it as a module, is Pyinit_MyModule (Python 3). When using C++ Builder, this function is exported as _Pyinit_MyModule, as mentioned. Problem is that it is Swig that exports this function, and I can't as a client of Swig change the calling convention (afaik) for this function.
I believe my initial belief that Python needed __stdcall for this functions is wrong, as VS by default is using cdecl, but without adding the '_', and it that works fine.
However, setting the compiler flag to suppress underscores don't work either, as then some of the functions in the Python import libraries are rendered invisible, and become unresolved externals. So perhaps this problem is more complex than it may first look. But I guess it has nothing todo with calling conventions.
cdecl is simply the typical default calling convention that every C++ compiler uses. If you want to use stdcall instead, you can certainly do that (makes sense why Python would expect stdcall since that is what the Win32 API uses).
In the module's C++ code, you can use __stdcall explicitly in the exported function declarations.
Or, you can change the default calling convention in C++Builder's project settings, and then omit any calling convention in the function declarations.
Now, to answer your question - when importing a pyd module, if the module uses cdecl, use ctypes.cdll to call its functions. If the module uses stdcall, use ctypes.windll instead. This is covered in Python's documentation:
https://docs.python.org/3/library/ctypes.html#loading-dynamic-link-libraries
16.16.1.1. Loading dynamic link libraries
ctypes exports the cdll, and on Windows windll and oledll objects, for loading dynamic link libraries.
You load libraries by accessing them as attributes of these objects. cdll loads libraries which export functions using the standard cdecl calling convention, while windll libraries call functions using the stdcall calling convention. oledll also uses the stdcall calling convention, and assumes the functions return a Windows HRESULT error code. The error code is used to automatically raise an OSError exception when the function call fails.
https://docs.python.org/3/faq/windows.html#is-a-pyd-file-the-same-as-a-dll
Is a *.pyd file the same as a DLL?
Yes, .pyd files are dll’s, but there are a few differences. If you have a DLL named foo.pyd, then it must have a function PyInit_foo(). You can then write Python “import foo”, and Python will search for foo.pyd (as well as foo.py, foo.pyc) and if it finds it, will attempt to call PyInit_foo() to initialize it. You do not link your .exe with foo.lib, as that would cause Windows to require the DLL to be present.
After some fiddling around, I can say that it is possible to create Python extensions using the C++ Builder compiler, swig and CMake.
Below is a brief overview of the steps that I used to wrap a simple C++ class (ATObject) to Python37.
The C++ header file is:
#ifndef atATObjectH
#define atATObjectH
#include <string>
//---------------------------------------------------------------------------
using std::string;
int MyTest(int r);
class ATObject
{
public:
ATObject();
virtual ~ATObject();
virtual const string getTypeName() const;
};
#endif
and source
#pragma hdrstop
#include "core/atATObject.h"
//---------------------------------------------------------------------------
ATObject::ATObject() {}
ATObject::~ATObject() {}
const string ATObject::getTypeName() const
{
return "TYPENAME NOT IMPLEMENTED";
}
int MyTest(int r)
{
return r;
}
1) Create import libraries using implip on the Python3 and Python37 dll's. Use implibs flag -aa, to get an import library that C++ builder understands. Put them in the Python37/libs folder.
2) Create the swig interface file that defines which class, functions and data to wrap. The swig interface file:
// atexplorer.i
%include "std_string.i"
%include "windows.i"
%module atexplorer
%{
#include "atATObject.h"
%}
//Expose class ATObject to Python
%include "atATObject.h"
3) Create CMake files for the project, using SWIG_ADD_LIBRARY to create the .pyd module, e.g.
SWIG_ADD_LIBRARY(atexplorer MODULE LANGUAGE python SOURCES
atexplorer.i ${ATAPI_ROOT}/source/core/atATObject.cpp )
SWIG_LINK_LIBRARIES (atexplorer
${PYTHON_LIB_FOLDER}/Python3_CG.lib
${PYTHON_LIB_FOLDER}/Python37_CG.lib
)
and make CMake pass the .def file to the linker by adding:
set (CMAKE_MODULE_LINKER_FLAGS ${CMAKE_CURRENT_SOURCE_DIR}/atexplorer.def)
The atexplorer.def file should look like this:
EXPORTS
PyInit__atexplorer=_PyInit__atexplorer
4) Compile the project, and confirm that you get a generated "MyModule"PYTHON_wrap.cxx and a MyModule.py file in your CMake build folder. The "MyModule"PYTHON_wrap.cxx file contains generated C++ code for the Python module, and the .py file contain generated Python code.
The Python module is named atexplorer.
Image below shows what is exported in the _atexplorer.pyd module.
Copy the .pyd and the .py files to Pythons site packages folder.
If successful, you will be able to import the module in Python, e.g.
The screen shot above shows how the module, atexplorer, is imported. It has a function called 'MyTest', that returns whatever its argument is, when executed.
It also has a class, ATObject, for which an object named 'a', is created. Last line prints the output of executing the class member function 'getTypeName()', which simply returns, TYPENAME NOT IMPLEMENTED.

c++ analog of c# "project reference"

My solution contains several c# projects.
It's easy to add "refernce" from one project to another(References-Add Reference-Project). After that I can use classes from referenced project.
How can I do the same for native c++ projects? What kind of projects should I create? Console application/DLL/Static library?
There are two things in C / C++ :
Headers file, that will tell your program what they can use (e.g. class, function prototype declaration)
Implementation, either as a
source code that you recompile with your program
static lib (.lib on windows)
dynamic lib (.dll on windows)
You need both to compile your program with parts from another project.
If you only need a class from a big library and you have the source of this library it may be easier to reference the file corresponding to this class (and its dependencies of course). But if you need more, you should add the other project's directory to the include path of your current project in VCC, and link against the library (either static or dynamic, according to your needs).

How to make COFF from obj file compiled with /GL option?

I've got a 3d party static library built with some older version of MSVC, and I successfully link it to my application in MSVC10 (VisualStudio2010). Now I upgraded to MSVC11, and I'm unable to link it:
2>LINK : fatal error C1047: The object or library file 'MyLib.lib' was
created with an older compiler than other objects; rebuild old objects
and libraries
I guess this happens because the lib was compiled with /GL option, so the object files don't really contain COFF, but some intermediate format.
I don't have the library source-code to re-compile, and I don't want to make a dll out of it to link dynamically.
Is there a way - maybe some undocumented trick - to "re-compile" these obj's to COFF and eventually link them to MSVC11 application?
Even if this was possible, you don't want to do this: linking object files that are built against different versions of the CRT usually ends in tears. More specifically, if two such object files both use the C++ Standard Library, it is all but certain that you will violate the One Definition Rule (ODR).
If you cannot rebuild the module using Visual C++ 2012, then you should encapsulate it within a dynamic library, built with Visual C++ 2010, and avoid using any C++ Standard Library types in the interface of that DLL.

VC6 linking conflict

I have an old c++ project compiled with VC6.
I need to statically link a new library to implement a new functionality.
Unfortunately the new library define a symbol (i.e. _inflate) that is already defined in a previously linked static library.
Of course I cannot get rid of either library, and of course I have no access to the library's source code.
Is there a way to avoid the linker error (LNK2005)?
If you know that the two versions of _inflate are identical, or at least "compatible", then you can use the /FORCE:Multiple linker option to force it to ignore name clashes.
Of course, if it links to a version of that code that is "incompatible" in any way it could cause undefined behaviour.

What is the difference between dllexport and dllimport?

I'm just looking for a simple, concise explanation of the difference between these two. MSDN doesn't go into a hell of a lot of detail here.
__declspec( dllexport ) - The class or function so tagged will be exported from the DLL it is built in. If you're building a DLL and you want an API, you'll need to use this or a separate .DEF file that defines the exports (MSDN). This is handy because it keeps the definition in one place, but the .DEF file provides more options.
__declspec( dllimport ) - The class or function so tagged will be imported from a DLL. This is not actually required - you need an import library anyway to make the linker happy. But when properly marked with dllimport, the compiler and linker have enough information to optimize the call; without it, you get normal static linking to a stub function in the import library, which adds unnecessary indirection. ONT1 ONT2
__declspec(dllexport) tells the linker that you want this object to be made available for other DLL's to import. It is used when creating a DLL that others can link to.
__declspec(dllimport) imports the implementation from a DLL so your application can use it.
I'm only a novice C/C++ developer, so perhaps someone's got a better explanation than I.
Two different use cases:
1) You are defining a class implementation within a dll. You want another program to use the class. Here you use dllexport as you are creating a class that you wish the dll to expose.
2) You are using a function provided by a dll. You include a header supplied with the dll. Here the header uses dllimport to bring in the implementation to be used by the current program.
Often the same header file is used in both cases and a macro defined. The build configuration defines the macro to be import or export depending which it needs.
Dllexport is used to mark a function as exported. You implement the function in your DLL and export it so it becomes available to anyone using your DLL.
Dllimport is the opposite: it marks a function as being imported from a DLL. In this case you only declare the function's signature and link your code with the library.

Resources