FFI example from book cannot find -lanneclib under Windows - windows

Error linking following the external c dll with call back example.
I have created anneclib.dll and scattered it ( and the lib) have even tried full path but still get the same error ( but with the full path) .
Error 1 error: linking with gcc failed: exit code: 1 note: "gcc"
"-Wl,--enable-long-section-names" "-fno-use-linker-plugin"
"-Wl,--nxcompat" "-static-libgcc" "-m64" "-L" "C:\Program Files\Rust
stable 1.0\bin\rustlib\x86_64-pc-windows-gnu\lib" "-o"
"obj\Debug\Anne.exe" "obj\Debug\Anne.o" "-Wl,--gc-sections"
"C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib\libstd-4e7c5e5c.rlib" "C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib\libcollections-4e7c5e5c.rlib"
"C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib\libunicode-4e7c5e5c.rlib" "C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib\librand-4e7c5e5c.rlib" "C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib\liballoc-4e7c5e5c.rlib" "C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib\liblibc-4e7c5e5c.rlib" "C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib\libcore-4e7c5e5c.rlib" "-L" "C:\Program Files\Rust stable
1.0\bin\rustlib\x86_64-pc-windows-gnu\lib" "-L" "C:\src\ann\anne.rust\anne.rust\Anne.rust\bin\x86_64-pc-windows-gnu"
"-L" "C:\src\ann\anne.rust\anne.rust\Anne\bin\x86_64-pc-windows-gnu"
"-Wl,--whole-archive" "-Wl,-Bstatic" "-Wl,--no-whole-archive"
"-Wl,-Bdynamic" "-lanneclib" "-lws2_32" "-luserenv" "-lcompiler-rt"
note: ld: cannot find -lanneclib
Using the Visual Studio Rust project.
Where should I put it ?
extern fn callback(a: i32) {
println!("I'm called from C with value {0}", a);
}
#[link(name = "anneclib")]
extern {
fn register_callback(cb: extern fn(i32)) -> i32;
fn trigger_callback();
}
fn main() {
unsafe {
register_callback(callback);
trigger_callback(); // Triggers the callback
}
}

In the error message you can see that the folder [your source folder]\bin\x86_64-pc-windows-gnu is added to the library path. You have to put your library into this folder. You may also have to add a 'lib' prefix to the library name.
Here is a small example that works for me:
A C file with a hello-function:
#include <stdio.h>
void hello() {
printf("Hello from C!\n");
}
Compile the C file to a shared library libhello.c using MinGW:
gcc -shared -o libhello.dll hello.c
The Rust file main.rs:
#[link(name = "hello")]
extern {
fn hello();
}
fn main() {
unsafe { hello(); }
}
Now you have to put (a copy of) the libhello.dll into the sub-folder \bin\x86_64-pc-windows-gnu:
+ bin
+ --- x86_64-pc-windows-gnu
+ --- libhello.dll
+ main.rs
And you should be able to compile it via
rustc main.rs
Note in order to execute the main.exe you also need a copy of the libhello.dll next to the main.exe or in the system path.

Related

How to control clang default include path

My copy of clang tries to include Visual Studio header files, this is the output of clang -v hello.cc
clang version 9.0.0 (https://github.com/llvm/llvm-project.git 4f93b8b56f5982d19b8b55b8c575887c17e15588)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: D:\llvm-project\build\Release\bin
"D:\\llvm-project\\build\\Release\\bin\\clang++.exe" -cc1 -triple x86_64-pc-windows-msvc19.21.27702 -emit-obj -mrelax-all
-mincremental-linker-compatible -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hello.cc -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -v -resource-dir "D:\\llvm-project\\build\\Release\\lib\\clang\\9.0.0"
-internal-isystem "D:\\llvm-project\\build\\Release\\lib\\clang\\9.0.0\\include"
-internal-isystem "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.21.27702\\ATLMFC\\include"
-internal-isystem "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.21.27702\\include"
-internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\ucrt" -internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\shared"
-internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\um" -internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\winrt"
-internal-isystem "C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.17763.0\\cppwinrt" -fdeprecated-macro
-fdebug-compilation-dir "D:\\llvm-project\\build\\Release\\bin" -ferror-limit 19 -fmessage-length 120 -fno-use-cxa-atexit -fms-extensions -fms-compatibility -fms-compatibility-version=19.21.27702 -std=c++14 -fdelayed-template-parsing -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o "C:\\Users\\krono\\AppData\\Local\\Temp\\hello-19d364.o" -x c++ hello.cc
clang -cc1 version 9.0.0 based upon LLVM 9.0.0svn default target x86_64-pc-windows-msvc
#include "..." search starts here:
#include <...> search starts here:
D:\llvm-project\build\Release\lib\clang\9.0.0\include
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\ATLMFC\include
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\ucrt
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\shared
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\um
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\winrt
C:\Program Files (x86)\Windows Kits\10\include\10.0.17763.0\cppwinrt
End of search list.
Presumably this was because I made some mistake when I built it (I built it with Visual Studio). How can I make it include the correct header files? I'm talking about a permanent solution rather than just overriding the include search path each time I compile.
Some background on this. I am trying to build a C++ program with clang and I get multiple multiply defined symbol errors, like this
error LNK2005: "bool const std::_Is_integral<bool>" (??$_Is_integral#_N#std##3_NB) already defined in ...
std::_Is_integral is a name defined in the Visual Studio <type_traits> header file. I believe that if I could get clang to include <type_traits> from the LLVM libcxx project this error would go away.
I have been hit by the same problem on several open source project myself. I do not have the answer but I can possibly give more details on the nature of the problem:
1) The problem is coming from STL headers in VS2019, which use the following constructs:
$ grep -r _Is_integral *
include/xtr1common:// STRUCT TEMPLATE _Is_integral
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral = // determine whether cv-unqualified type _Ty is integral
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral = false; // determine whether cv-unqualified type argument is integral
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<bool> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<char> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<signed char> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<unsigned char> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<wchar_t> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<char16_t> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<char32_t> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<short> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<unsigned short> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<int> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<unsigned int> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<long> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<unsigned long> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<long long> = true;
include/xtr1common:_INLINE_VAR constexpr bool _Is_integral<unsigned long long> = true;
include/xtr1common:_INLINE_VAR constexpr bool is_integral_v = _Is_integral<remove_cv_t<_Ty>>; // determine whether _Ty is integral
The behavior is related to how "if constexpr" is evaluted by the compiler. According to the standard it should be supported from C++17, but MSVC compiler silently supports it when running (in default) C++14 mode.
clang-cl on the other hand does not generate C++17 code, when run in C++14 mode, so it generates all those exported symbols and then lets the (MS) linker complain about them.
The solution I found so far (which may or may not be applicable depending on the project) is forcing clang-cl into C++17, which then compiles the constructs using "if constexpr" correctly (with no symbols).
The other temporary workaround may be using /force:multiple in linker flags to force the linking. Since their values should not change, the multiple definition should not be problem, but it is also suboptimal.
Apparently, MS is aware of the problem, but do not want to change the library.
https://developercommunity.visualstudio.com/content/problem/426829/xtgmathh-and-other-microsoft-include-files-use-if.html
Concerning the usage of Clang's "native" STL, I would expect one would need to use also "native" clang (i.e. not clang-cl, which is drop down replacement for MSVC). How this might go then however I have no idea.

Sharing static library between .dll(runtime loading) and .exe

I have a .lib library which provides APIs which have global variables like file/device handles, these APIs are going to be used by the application(.exe) by linking with .lib statically. The application does some initialization using APIs provided by .lib (like opening device/file etc) and loads the .dll during run time to perform writes and reads to the device/file using APIs provided by .lib. The problem is when I link the static library with both .exe and .dll they have different copies of libraries and the initialization done by the application is not retained when .dll is opened during run-time (since .dll and .exe seem to be working with their own copy of .lib). This problem is solved when I make .dll instead of static library and export all APIs and import them in .exe and .dll.
But I want to make the .exe standalone without any .dll dependencies except for run-time .dll .
Here is sample code for scenario
main.c (.exe)
#include <stdio.h>
#include <windows.h>
#include "static_lib.h"
typedef void (*FNPTR)(void);
FNPTR functionname;
int main(){
HINSTANCE hLib;
LPTSTR dllname = "dynamic.dll";
hLib=LoadLibrary(dllname);
if(hLib==NULL)
{
printf("Unable to load dll %s\n", dllname);
return 0;
}
functionname=(FNPTR)GetProcAddress((HMODULE)hLib, (LPCSTR)"dyn_main");
if((functionname==NULL))
{
printf("unable to load test function %s\n", dllname);
FreeLibrary((HMODULE)hLib);
return 0;
}
printf("Var in main: ");
test_func();
printf("calling dyn_main:");
functionname();
printf("back to main:");
printvar();
FreeLibrary((HMODULE)hLib);
return 1;
}
static_lib.c (static library)
#include <stdio.h>
#include <windows.h>
#include "static_lib.h"
int var; //can be file or device handle
int test_func(){ //initializes the device
change_var();
printvar();
return 1;
}
void printvar(void){ //write/read device/file
printf("%d\n",var);
return;
}
void change_var(void){ //opens device/file
var = 1;
return;
}
static_lib.h
#ifndef _STATIC_LIB_H_
#define _STATIC_LIB_H_
#if defined (DLL_EXPORT)
#define DLL_IMPORT_EXPORT __declspec(dllexport)
#else
#define DLL_IMPORT_EXPORT __declspec(dllimport)
#endif
DLL_IMPORT_EXPORT void change_var(void);
DLL_IMPORT_EXPORT void printvar(void);
DLL_IMPORT_EXPORT int test_func();
#endif
dynamic.c (.dll)
#include <stdio.h>
#include <windows.h>
#include "static_lib.h"
__declspec(dllexport) void dyn_main(void){
printvar(); //uses the device
return;
}
The command line for compiling with dynamic linking is
cl /c /nologo main.c dynamic.c
cl /c /nologo /DDLL_EXPORT static_lib.c
LINK /nologo /DLL static_lib.obj
LINK /nologo /DLL dynamic.obj static_lib.lib
LINK /nologo main.obj static_lib.lib
The output is:
main.exe
Var in main: 1
calling dyn_main:1
back to main:1
But when I make a static library and link with .exe and .dll
cl /c /nologo main.c dynamic.c static_lib.c
LIB static_lib.obj
LINK /nologo /DLL dynamic.obj static_lib.lib
LINK /nologo main.obj static_lib.lib
The output is
main.exe
Var in main: 1
calling dyn_main:0
back to main:1
And in real scenario the program crashes as it is invalid device/file handle inside .dll.
Is there anyway to export APIs into .dll from .exe without linker giving unresolved symbol error and maintaining only one copy of static library used by .dll and .exe?
I have searched for the problem and I found this: Dynamic Loading of my DLL with Static Lib in Windows Environment
It says we cannot do this in windows environment. But I want to make sure before thinking of other alternatives.

How do I use the clang static analyzer with msbuild on Windows?

The binary windows installer for clang includes scan-build but when you run it with msbuild nothing happens. Even if I do something like:
"C:\Program Files\LLVM\bin\scan-build.bat" "C:\Program Files\LLVM\bin\clang.exe" test.cpp
I get something like:
scan-build: Using 'C:\Program Files\LLVM\bin\clang.exe' for static analysis
scan-build: Removed Directory '....'
scan-build: No Bugs found
Where test.cpp is:
void DivideByZero(int z){
if (z == 0) {
int x = 1 / z;
}
}
int main() {
int *i = nullptr;
*i = 42;
DivideByZero(0);
}
If I use the following I get some warnings:
"C:\Program Files\LLVM\bin\clang.exe" --analyze test.cpp
So back to my question. How does one get this to work with MSBUild? What is scan-build actually doing and should I use it or --analyze? What is the difference?

Windows 7 MinGW compilation error using Boost ASIO

Having trouble compiling the following C++ code on Windows 7:
#include <boost/asio.hpp>
#include <iostream>
void handler1(const boost::system::error_code &ec)
{
std::cout << "5 s." << std::endl;
}
void handler2(const boost::system::error_code &ec)
{
std::cout << "10 s." << std::endl;
}
int main()
{
boost::asio::io_service io_service;
boost::asio::deadline_timer timer1(io_service, boost::posix_time::seconds(5));
timer1.async_wait(handler1);
boost::asio::deadline_timer timer2(io_service, boost::posix_time::seconds(10));
timer2.async_wait(handler2);
io_service.run();
}
I have MinGW installed (gcc 4.8.1) in c:\mingw with my PATH set up correctly. I have downloaded boost and declared environment variable BOOST_ROOT to be the path where it resides. I have gone through the bootstrap and b2 procedure for boost. I now try and compile:
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -o main main.cpp
Gives a bunch of error: '::UnregisterWaitEx' has not been declared errors
I then search a bit and see I may need to link boost_system. So:
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -lboost_system -o main main.cpp
Same errors. Thought I'd try specify library path. Did a search for boost_system and found static libs (libboost_system-mgw48-mt-1_55.a) in %BOOST_ROOT%/stage/lib. So
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -L%BOOST_ROOT%/stage/lib -lboost_system-mgw48-mt-1_55 -o main main.cpp
Same errors. So I search again and see others suggesting appending a -D-D_WIN32_WINNT=0x0601. So
c:\path\to\sandbox> g++ -I%BOOST_ROOT% -L%BOOST_ROOT%/stage/lib -lboost_system-mgw48-mt-1_55 -o main main.cpp -D_WIN32_WINNT=0x0601
And the inevitable errors:
c:\mingw\include\mswsock.h:125:20: error: 'WSAPOLLFD' was not declared in this scope
int WSAAPI WSAPoll(WSAPOLLFD, ULONG, INT);
^
c:\mingw\include\mswsock.h:125:36: error: expected primary-expression before ',' token
int WSAAPI WSAPoll(WSAPOLLFD, ULONG, INT);
^
c:\mingw\include\mswsock.h:125:41: error: expected primary-expression before ')' token
int WSAAPI WSAPoll(WSAPOLLFD, ULONG, INT);
^
c:\mingw\include\mswsock.h:125:41: error: expression list treated as compound expression in initializer [-fpermissive]
Where am I going wrong?
I went ahead and rebuilt Boost again with b2 toolset=gcc --build-type=complete. Same thing happened. Finally, after all that, it turned out all I needed was to put the linking at the end of the command:
C:\path\to\sandbox> g++ -D_WIN32_WINNT=0x0601 -I%BOOST_ROOT% -L%BOOST_ROOT%\stage\lib -o boosttest boosttest.cpp -lwsock32 -lws2_32 -lboost_system-mgw48-mt-d-1_55
C:\path\to\sandbox> boosttest.exe
5 s.
10 s.
The -D_WIN32_WINNT was still necessary and, for anyone who has skipped the other comments, I had to patch winsock.h as detailed http://sourceforge.net/p/mingw/bugs/1980/. And remember to put %BOOST_ROOT%\stage\lib in your PATH so Windows can find the dll at runtime.
Arduous

Compiling C++ that uses Boost::mpi with Xcode 4

I'm trying to run the following simple example from Xcode4:
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>
namespace mpi = boost::mpi;
int main(int argc, char* argv[])
{
mpi::environment env(argc, argv);
mpi::communicator world;
std::cout << "I am process " << world.rank() << " of " << world.size()
<< "." << std::endl;
return 0;
}
I've added libboost_mpi and libboost_serialization to Xcode, and compiling using the default LLVM returns :
/usr/local/include/boost/mpi/communicator.hpp:1329:9: error: call to
implicitly-deleted copy constructor of 'boost::mpi::communicator'
: comm(comm), source(source), tag(tag), ia(comm), value(value)
^ ~~~~
However, I can compile and run using
mpic++ -I/usr/local/include main.cpp -L/usr/local/lib
-lboost_mpi -lboost_serialization
Although mpic++ seems to be calling through to LLVM:
$ mpic++
i686-apple-darwin11-llvm-g++-4.2: no input files
Anyways, I tried adding mpic++ as a compiler option in Xcode 4. I can run
$ sudo opensnoop -n Xcode | grep mpicc.xcspec
and see that the spec file is being loaded by Xcode, but I don't see any MPICC option. My spec file is fairly simple:
/**
Xcode Compiler Specification for MPICC
*/
{ Type = Compiler;
Identifier = com.apple.compilers.mpicc;
BasedOn = com.apple.compilers.gcc.4_2;
Name = “MPICC”;
Version = “Default”;
Description = “MPI GNU C/C++ Compiler 4.0″;
ExecPath = “/usr/local/bin/mpicc”;
PrecompStyle = pch;
}
and it's stored in
/Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins/LLVM GCC 4.2.xcplugin/Contents/Resources/mpicc.xcspec
So this works:
link binary with:
libmpi_cxx.dylib
libmpi.dylib
libboost_mpi.dylib
libboost_serialization.dylib
Change compiler (under build options) to LLVM GCC 4.2 (hinted at by running mpic++ directly, which reports that it's using llvm gcc 4.2 internally)
Under targets, build phases, compile sources, add the compiler option "-lm" to report that you need to link with libm. Credit to #pyCthon for pointing out mpic++ --showme:link which revealed the final library that was allowing it to build successfully from the command line

Resources