How to control clang default include path - visual-studio

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.

Related

Cuda C++ template undefined reference Compilation issue while porting a visual studio project to linux

I am trying to compile the following code ([cuShiftOr]) to a linux box. Original code is running on Visual Studio 2013 in Windows.
My strategy is to compile all .cu files like below:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 --compile -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -fexceptions -ffunction-sections -fdata-sections -fpermissive" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -c CuShiftOr/device/hybrid.cu -o objs/CuShiftOr/device/hybrid.cu.o
Likewise for the rest.
At the final stage link everything together by running:
nvcc -std=c++11 -Icpp11-range -gencode=arch=compute_52,code=\"sm_52,compute_52\" --use-local-env --cl-version 2013 -maxrregcount=0 --machine 64 -cudart static -DWIN32 -DWIN64 -DNDEBUG -D_CONSOLE -D_MBCS -I$HOME/cuShiftOr/CuShiftOr -I$HOME/cuShiftOr/CuShiftOrBenchmark -I$HOME/cuShiftOr/tinyformat -Xcompiler "-fPIC -std=c++11 -Icpp11-range -fexceptions -ffunction-sections -fdata-sections -fpermissive -Wnon-template-friend" -ccbin=/opt/cray/pe/craype/2.5.10/bin/CC -o CuShiftOrBenchmark.a objs/CuShiftOr/device/hybrid.cu.o objs/CuShiftOr/util/op.cu.o objs/CuShiftOr/device/segment.cu.o objs/CuShiftOr/host.cu.o objs/CuShiftOr/util/timer.cu.o objs/CuShiftOr/util/file.cu.o objs/CuShiftOr/util/generator.cu.o objs/CuShiftOrBenchmark/kernel.cu.o -lm
However that leads me this undefined reference issue:
objs/CuShiftOrBenchmark/kernel.cu.o: In function `void run_benchmark<unsigned int>(std::ostream&, cushiftor::device::Handler<unsigned int>*, long, unsigned int, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
tmpxft_00003ea2_00000000-4_kernel.cudafe1.cpp:(.text._Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE[_Z13run_benchmarkIjEvRSoPN9cushiftor6device7HandlerIT_EEljiNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE]+0x203): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
inside op.cuh it is defined as:
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
template<typename word>
__host__ __device__ __forceinline__ word ones(int m) {
return ~word(0) >> (bit<word>::size - m);
}
and then on kernel.cu we have:
#include "util/op.cuh"
using cushiftor::util::op::bit;
using cushiftor::util::op::bytepack;
using cushiftor::util::op::div_up;
using cushiftor::util::op::round_up;
using cushiftor::util::op::shuffle_up;
Further more compiling with Visual Studio 2013 (which works since the project was made on that) shows some instantiations that I am not sure if g++ is doing e.g:
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(209): warning C4244: 'argument' : conversion from 'int64_t' to 'cushiftor::env::datasize_t', possible loss of data
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(230) : see reference to function template instantiation 'void benchmark_with_file<word>(cushiftor::device::Handler<word> *)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
2>C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(86): warning C4018: '<=' : signed/unsigned mismatch
2> C:/Users/A/Desktop/cuShiftOr/CuShiftOrBenchmark/kernel.cu(132) : see reference to function template instantiation 'void run_benchmark<word>(std::ostream &,cushiftor::device::Handler<word> *,int64_t,cushiftor::env::datasize_t,int,std::string)' being compiled
2> with
2> [
2> word=unsigned int
2> ]
Now my C++11 template knowledge is very limited but I did try to instantiate also inside the kernel.cu by adding:
template class cushiftor::util::op::bit<unsigned int>;
However to no avail... Any tips are very welcomed!
I believe this question is essentially a duplicate of this one. However simply marking it as such with no explanation may be a bit obscure. Therefore I'm going to provide a CW answer in the hopes that someone may improve it or correct me if I am wrong.
A possible MCVE derived from the code is as follows (note that I'm converting to using g++ directly rather than nvcc, as the manifestation and workarounds are the same):
$ cat test.cpp
#include <iostream>
namespace cushiftor {
namespace util {
namespace op {
template<typename type>
struct bit {
static const int size = sizeof(type) * 8;
};
}
}
}
#ifdef FIX2
void f(const int data){
#else
void f(const int &data){
#endif
std::cout << "size of type in bits is: " << data << std::endl;
}
using cushiftor::util::op::bit;
#ifdef FIX1
template <typename T> const int bit<T>::size;
#endif
template<typename word>
void run_benchmark() {
f(bit<word>::size);
}
int main(){
run_benchmark<unsigned>();
}
$ g++ -o test test.cpp
/tmp/ccCW51e3.o: In function `void run_benchmark<unsigned int>()':
test.cpp:(.text._Z13run_benchmarkIjEvv[_Z13run_benchmarkIjEvv]+0x5): undefined reference to `cushiftor::util::op::bit<unsigned int>::size'
collect2: error: ld returned 1 exit status
$ g++ -DFIX1 -o test test.cpp
$ g++ -DFIX2 -o test test.cpp
$
This MCVE was created based on inspection of relevant code in kernel.cu, tinyformat.h, and op.cuh, in the original cuShiftOr project (and paper).
We see that if we compile the code as-is, it generates a similar error to that reported in the question.
Compiling with -DFIX2 demonstrates that taking the item in question (bit::size) as a reference argument is essential to witnessing of the issue.
Compiling with -DFIX1 eliminates the issue, and I believe is the correct approach in this case.
The explanation for this issue seems to be that the compiler may treat the static const member as a compile-time constant, unless it is "used" in the code. ("Used" has a special language-specific meaning here.) If it is "used" in the code, then the compiler must be able to take the address of it (sensible in the case of a reference parameter) and to take the address of it, the class/struct definition is not sufficient. (It is apparently only a declaration even though it appears in the class/struct definition. The declaration is sufficient for usage equivalently to a compile-time constant, but is not sufficient for the case where we wish to take the address of it.)
From here:
If a static data member is of const integral or const enumeration type, its declaration in the class definition can specify a constant-initializer which shall be an integral constant expression (5.19) In that case, the member can appear in integral constant expressions. The member shall still be defined in a namespace scope if it is used in the program
I believe the FIX1 code modification satisfies the bolded requirement above.
With the above preamble, I believe it is valid to mark this as a duplicate.
With respect to the behavior of the original project on windows, I would conjecture that compilers may have leeway in enforcement of this, and may in fact provide referenceable member symbols even when the program does not explicitly define them.

Why doesn't alignas compile when used in a static declaration with clang?

I have a compilation error on clang and a warning with gcc with this code:
static alignas(16) int one_s = 1; // clang: error: an attribute list cannot appear here; gcc: warning: attribute ignored;
static __attribute__((aligned(16))) int zero_s = 0; // on the other hand this works well on both compilers...
alignas(16) int one = 1; // this also works on both compilers
__attribute__((aligned(16))) int zero = 0; // as well as this
Does anyone know why alignas is not accepted in the declaration that contains the static keyword? I used the --std=c++11 compiler option with both gcc and clang. (Edit: I used clang 3.4 and above and gcc 4.8 and above)
Note that when compiling with Visual Studio (CL 19 RC) I don't get an error when using alignas in a static declaration like that.

FFI example from book cannot find -lanneclib under 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.

Embedding Tcl in a C program

I am trying to create a simple c++ console app that calls the nagelfar syntax checker on a script. I followed the directions here: http://wiki.tcl.tk/19919 , adding the tclstub85.lib to my input, adding the tcl lib directory to my additional libraries, and adding my header directory as well. Linking fails with:
main.obj : error LNK2001: unresolved external symbol _tclStubsPtr
This is my command line for linking:
/OUT:"C:\Users\######\Documents\Visual Studio 2005\Projects\Nagelfar\Release\Nagelfar.exe"
/NOLOGO /LIBPATH:"C:\Tcl\lib" /MANIFEST
/MANIFESTFILE:"Release\Nagelfar.exe.intermediate.manifest" /DEBUG
/PDB:"c:\users\######\documents\visual studio 2005\projects\nagelfar\release\Nagelfar.pdb"
/OPT:REF /OPT:ICF /LTCG /MACHINE:X86 /ERRORREPORT:PROMPT C:\Tcl\lib\tclstub85.lib
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib
shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
This is the full source code, which I can compile and run fine in Linux using g++:
#include <stdlib.h>
#include <stdio.h>
#include <tcl.h>
#include <string.h>
Tcl_Interp * tcl_interp ;
char fileToCheck[] = "test.tcl";
char dbFile[] = "syntaxdb.tcl";
int main () {
int code, argc;
const char **argv;
char command[1024];
char *results = NULL;
tcl_interp = Tcl_CreateInterp();
Tcl_SetVar2(tcl_interp, "::Nagelfar", "embedded", "1", 0);
code = Tcl_EvalFile(tcl_interp, "nagelfar.tcl");
Tcl_LinkVar(tcl_interp, "::Nagelfar(chkResult)", (char *)&results, TCL_LINK_STRING);
sprintf(command, "synCheck %s %s", fileToCheck, dbFile);
code = Tcl_Eval(tcl_interp, command);
printf("Raw Result: \r\n %s\r\n", results);
code = Tcl_SplitList(tcl_interp, results, &argc, &argv);
{
int i;
for (i = 0; i < argc; ++i)
{
printf("%d/%d: %s\r\n", i+1, argc, argv[i]);
}
}
Tcl_Free(results);
return 0;
}
Solved my own problem: I had x64 ActiveTcl but was linking a 32 bit project. Using the x86 ActiveTcl distribution fixed my issues.
Your error message tells us that you are expecting a stub table (Tcl's goes by the name tclStubPtr once all the macros are expanded), which in turn says that defining the preprocessor symbol USE_TCL_STUBS. That symbol is for use in the case where you are writing a library that is providing extra functionality to Tcl. However, in the case where you are writing a main application that calls functions in the Tcl library — such as “run this code” — you can't (easily) use the stubs mechanism as you'd be needing the stub table before Tcl is in a position to be able to provide it to you.
The fix is to not define USE_TCL_STUBS and to link against the main Tcl library (probably C:\Tcl\lib\tcl85.dll on your system) instead of tclstub85.lib. (I don't know enough about setting up Visual Studio to say what the details of that configuration are.)
You should also add this line to your code before the call to Tcl_CreateInterp():
Tcl_FindExecutable(NULL);
That call is used to allow the Tcl library core to initialize itself, doing little things like getting the memory manager and filesystem interface layer working.
Solved my own problem: I had x64 ActiveTcl but was linking a 32 bit project. Using the x86 ActiveTcl distribution fixed my issues.

cegcc: failed linking import library compiled with vc++ (mangling issue)

I have application for Windows Mobile 6. To build it I use cegcc (arm-mingw32ce).
Now I have new device with new SDK and some functions from this SDK must be added to this application.
Here comes SDK.
header.h
#ifndef _HEADER_H_
#define _HEADER_H_
#include <windows.h>
#ifndef _SOME_FLAG_
extern "C"
{
#endif
BOOL foo(DWORD *lpdwParam1, DWORD *lpdwParam2);
#ifndef _SOME_FLAG_
}
#endif
#endif
library.lib (this is probably import library compiled with VC++, there is library.dll on device)
Some output from "dumpbin /all library.lib"
2DA0 ?foo##YAHPAK0#Z
2DA0 __imp_?foo##YAHPAK0#Z
Archive member name at 2DA0: library.dll/
correct header end
Version : 0
Machine : 1C2 (Thumb)
SizeOfData : 0000002B
DLL name : library.dll
Symbol name : ?foo##YAHPAK0#Z (int __cdecl foo(unsigned long *,unsigned long *))
Type : code
Name type : undecorate
Hint : 14
Name : foo
I'm able to use this SDK in VS2k5 (installation of Windows Mobile SDK was needed...) but compiling with cegcc fail.
I was trying to compile and link it as C and Cpp. With and without _SOME_FLAG_ defined (C compilation with this flag set fail on extern "C" of course).
The results are:
undefined reference to `foo'
when C compiled or Cpp compiled with extern "C" and
undefined reference to `foo(unsigned long*, unsigned long*)'
when Cpp compiled without extern "C".
Compile:
gcc -O2 -Wall -Wextra -pedantic -Wno-long-long -g -c -DUNICODE -D_UNICODE -Ic:\inc sample.c
Linking:
gcc -static -mconsole -o sample obj\sample.o -lc:\lib\library.lib -laygshell
When I Cpp compile I'm only changing sample.c to sample.cpp (there is only main with simple foo call).
It look like there is a mangling problem (vc++ vs gcc). I've tried to add __attribute__((dllimport)) and __attribute__((cdecl))
How can I solve this problem? Any ideas?
Problem solved. I've forget about possibility of run-time dynamic linking
#include <windows.h>
#include <winbase.h>
#include <header.h>
HINSTANCE dllinst = NULL;
typedef BOOL (CALLBACK LP_FOO)(DWORD *lpdwParam1, DWORD *lpdwParam2);
static LP_FOO Foo;
dllinst = LoadLibrary("library.dll");
Foo = (LP_FOO) GetProcAddress((HMODULE) dllinst, "foo");
Now I can use Foo same as foo.

Resources