Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LNK2019 unresolved symbol for Vec<SharedStruct> using MSVC #1362

Open
stery28 opened this issue Jul 16, 2024 · 0 comments
Open

LNK2019 unresolved symbol for Vec<SharedStruct> using MSVC #1362

stery28 opened this issue Jul 16, 2024 · 0 comments

Comments

@stery28
Copy link

stery28 commented Jul 16, 2024

Hello!

I'm trying to expose a function taking an opaque type as arugment and returning a Vec containing a shared struct type (fn get_inner_vec(some_outer: &SomeOuterOpaqueStruct) -> Vec<SomeInnerSharedStruct>):

// inner.rs
#[cxx::bridge(namespace = "cxx_test_vec::inner")]
pub(crate) mod ffi {
    #[derive(Clone)]
    pub(crate) struct SomeInnerSharedStruct {
        pub(crate) f1: i32,
        pub(crate) f2: i32,
    }
}
// lib.rs
use ffi::SomeInnerSharedStruct;

mod inner;

pub(crate) struct SomeOuterOpaqueStruct {
    pub(crate) inner_vec: Vec<SomeInnerSharedStruct>,
    pub(crate) some_flag: bool,
}

impl SomeOuterOpaqueStruct {
    fn new(inner_vec: Vec<SomeInnerSharedStruct>) -> Self {
        Self {
            inner_vec,
            some_flag: false,
        }
    }

}

fn get_inner_vec(some_outer: &SomeOuterOpaqueStruct) -> Vec<SomeInnerSharedStruct> {
    some_outer.inner_vec.to_owned()
}

pub(crate) fn make_inner_vec() -> Vec<SomeInnerSharedStruct> {
    vec![
        SomeInnerSharedStruct { f1: 1, f2: 2 },
        SomeInnerSharedStruct { f1: 4, f2: 5 },
    ]
}

pub(crate) fn new_outer() -> Box<SomeOuterOpaqueStruct> {
    Box::new(SomeOuterOpaqueStruct::new(make_inner_vec()))
}

#[cxx::bridge(namespace = "cxx_test_vec::outer")]
mod ffi {
    #[namespace = "cxx_test_vec::inner"]
    extern "C++" {
        include!("cxx-test-vec/src/inner.rs.h");
        type SomeInnerSharedStruct = crate::inner::ffi::SomeInnerSharedStruct;
    }

    extern "Rust" {
        type SomeOuterOpaqueStruct;
        fn new_outer() -> Box<SomeOuterOpaqueStruct>;
        fn get_inner_vec(some_outer: &SomeOuterOpaqueStruct) -> Vec<SomeInnerSharedStruct>;
    }
}

#[cfg(test)]
mod tests {
    use crate::{get_inner_vec, new_outer};


    #[test]
    fn test_fn() {
        let outer_struct = new_outer();
        let inner_vec = get_inner_vec(&outer_struct);

        assert_ne!(inner_vec.len(), 0);
    }
}
// build.rs
fn main() {
    let source_files = vec![
        "src/lib.rs",
        "src/inner.rs",
    ];

    cxx_build::bridges(source_files)
    .std("c++14")
    .compile("cxx-test-vec");

    println!("cargo:rerun-if-changed=src/lib.rs");
    println!("cargo:rerun-if-changed=src/inner.rs");
}
# Cargo.toml
[package]
name = "cxx-test-vec"
version = "0.1.0"
edition = "2021"


[lib]
crate-type = ["staticlib"]

[dependencies]
cxx = "1.0"

[build-dependencies]
cxx-build = "1.0"

cargo build runs fine, but I encounter an unresolved symbol error when running cargo test using the stable-x86_64-pc-windows-msvc toolchain. I'm getting the same error when actually linking the library in a C++ project, but I'll focus only on cargo test for now. I think it's something MSVC specific, because I didn't encounter any errors running cargo test on macOS, but unfortunately I need to use MSVC in this project.

The error:

note: cxx-test-vec.lib(1c4c8df760424d6e-lib.rs.o) : error LNK2019: unresolved external symbol 
"public: __cdecl rust::cxxbridge1::Vec<struct cxx_test_vec::inner::SomeInnerSharedStruct>::Vec<struct cxx_test_vec::inner::SomeInnerSharedStruct>(void)" 
(??0?$Vec@USomeInnerSharedStruct@inner@cxx_test_vec@@@cxxbridge1@rust@@QEAA@XZ) referenced in function 
"public: __cdecl rust::cxxbridge1::Vec<struct cxx_test_vec::inner::SomeInnerSharedStruct>::Vec<struct cxx_test_vec::inner::SomeInnerSharedStruct>(class rust::cxxbridge1::Vec<struct cxx_test_vec::inner::SomeInnerSharedStruct> &&)" 
(??0?$Vec@USomeInnerSharedStruct@inner@cxx_test_vec@@@cxxbridge1@rust@@QEAA@$$QEAV012@@Z)

This also doesn't happen if both the function returning Vec<SomeInnerSharedStruct> and SomeInnerSharedStruct's definition are in the same cxx::bridge module, so it might have something to do with "reimporting" the shared struct from another bridge.

Other details:
rustc 1.79.0 (129f3b996 2024-06-10)
Windows 11 22H2 build 22621.3880
Microsoft Visual Studio Community 2022, MSVC 14.34.31933 (link.exe version 14.34.31937.0, cl.exe version 19.34.31937 for x64)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant