Pregunta Vinculación a una lib estática compilada con MSVC


Estoy tratando de enlazar con un simple C lib en Windows contra la biblioteca Rust

Mi lib es .h

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

.cpp

#include <stdio.h>

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

Mi archivo rust

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

El enlace falla al dar un error con uno de los símbolos de datos

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

La biblioteca está basada en MSVC2013 como una lib simple estática. La cadena "hello world" está en la sección de datos, por lo que no esperaría que cause un error de enlace. ¿Hay alguna configuración específica que deba tener en cuenta al vincular bibliotecas C en Windows?

Por cierto, es una lib de MSVC de 32 bits.


5
2018-06-09 07:29


origen


Respuestas:


Ok, algunas cosas. En primer lugar, no existe tal cosa como una "DLL estática": una DLL es una dinamicamente biblioteca enlazada.

En segundo lugar, Rust utiliza la cadena de herramientas MinGW y el tiempo de ejecución. Mezclar tiempos de ejecución de MSVC y MinGW puede causar que ocurran cosas extrañas, por lo que es mejor evitarlo si es posible. El óxido ha aterrizado recientemente muy temprano Soporte para la construcción utilizando el tiempo de ejecución de MSVC.

Sin embargo, tu poder toma esto específico Ejemplo para trabajar, aparentemente sin efectos nocivos. Solo necesitas cambiar algunas cosas:

  • Necesita usar una biblioteca dinámica; mi entendimiento es que esto hace que las malas interacciones sean un poco menos probables.

  • Necesitas actualmente compilar say_hello con C vinculación, no C++ enlace. Hiciste esto en el encabezado, pero no en el archivo fuente.

  • Necesita exportar públicamente say_hello de la biblioteca.

Así:

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

En mi máquina, esto produce hello.exe y hello.dll; cuando se ejecuta, hello.exe imprime hello world.


9
2018-06-09 07:52