Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking to a static lib compiled with MSVC

Tags:

dll

rust

I'm trying to link with a simple C lib on windows against Rust library

My lib is .h

extern "C" {
    void say_hello(const char* s);
}

.cpp

#include <stdio.h>

void say_hello(const char* s) {
    printf("hello world");
}

My Rust file

#[link(name="CDbax", kind="static")]
extern "C" {
    fn say_hello(s: *const libc::c_char) -> () ;
}

Linking fails by giving an error with one of the data symbols

error: linking with `gcc` failed: exit code: 1
note: "gcc" "-Wl,--enable-long-section-names" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-Wl,--large-address-aware" "-shared-libgcc" "-L" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib" "e:\Rust\DBTools\DBAnalytics\target\debug\DBAnalytics.o" "-o" "e:\Rust\DBTools\DBAnalytics\target\debug\DBAnalytics.dll" "e:\Rust\DBTools\DBAnalytics\target\debug\DBAnalytics.metadata.o" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib\libstd-11582ce5.rlib" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib\libcollections-11582ce5.rlib" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib\librustc_unicode-11582ce5.rlib" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib\librand-11582ce5.rlib" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib\liballoc-11582ce5.rlib" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib\liblibc-11582ce5.rlib" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib\libcore-11582ce5.rlib" "-L" "e:\Rust\DBTools\DBAnalytics\target\debug" "-L" "e:\Rust\DBTools\DBAnalytics\target\debug\deps" "-L" "C:\Program Files (x86)\Rust 1.2\bin\rustlib\i686-pc-windows-gnu\lib" "-L" "e:\Rust\DBTools\DBAnalytics\.rust\bin\i686-pc-windows-gnu" "-L" "e:\Rust\DBTools\DBAnalytics\bin\i686-pc-windows-gnu" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "CDbax" "-Wl,--no-whole-archive" "-Wl,-Bdynamic" "-l" "ws2_32" "-l" "userenv" "-l" "advapi32" "-shared" "-l" "compiler-rt"
note: Warning: corrupt .drectve at end of def file
Cannot export ??_C@_0M@LACCCNMM@hello?5world?$AA@: symbol not found

The library is build on MSVC2013 as a simple static lib. The string "hello world" is in the data section, so I wouldn't expect it to cause a link error. Are there some specific settings I need to be aware about when linking with C libraries on windows?

Btw it's 32bit MSVC lib.

like image 628
Delta_Fore Avatar asked Jun 09 '15 07:06

Delta_Fore


People also ask

Can a DLL link to static library?

When your DLL refers to an external content (like function or variable), it is resolved at linking time - together with all dependencies. But that's all. If your static library has a function named print_sample_string() , but your DLL does not use it, it won't be attached to DLL image.

How do I link a static library in Visual Studio 2015?

To create a static library project in Visual Studio 2015 On the menu bar, choose File > New > Project. In the New Project dialog box, select Installed > Templates > Visual C++ > Win32. In the center pane, select Win32 Console Application. Specify a name for the project—for example, MathLibrary—in the Name box.


1 Answers

Ok, a few things. First of all, there's no such thing as a "static DLL": a DLL is a dynamically linked library.

Secondly, Rust uses the MinGW toolchain and runtime. Mixing MSVC and MinGW runtimes can cause odd things to happen, so it's probably best avoided if at all possible. Rust has only recently landed very early support for building using the MSVC runtime.

However, you can get this specific example to work, apparently without any ill effects. You just need to change a few things:

  • You need to use a dynamic library; my understanding is that this makes bad interactions a little less likely.

  • You need to actually compile say_hello with C linkage, not C++ linkage. You did this in the header, but not in the source file.

  • You need to publicly export say_hello from the library.

Thus:

hello.rs:

#[link(name="hello", kind="dylib")]
extern {
    fn say_hello();
}

fn main() {
    unsafe { say_hello(); }
}

hello.h:

#ifndef HELLO_H
#define HELLO_H

extern "C" {
    __declspec(dllexport) void say_hello();
}

#endif

hello.cpp:

#include <cstdio>

#include "hello.h"

void say_hello() {
    printf("hello world\n");
}

build.cmd

cl /LD hello.cpp
rustc -L. hello.rs

On my machine, this produces hello.exe and hello.dll; when run, hello.exe prints out hello world.

like image 166
DK. Avatar answered Sep 23 '22 07:09

DK.