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

does it work in a Windows cdylib? #1115

Closed
vpopescu opened this issue Oct 20, 2022 · 7 comments
Closed

does it work in a Windows cdylib? #1115

vpopescu opened this issue Oct 20, 2022 · 7 comments
Labels
linking Issues that manifest as link failures support

Comments

@vpopescu
Copy link

Is using this in a cdylib (on windows) supported?

I am trying to follow the documentation, and although I can get it to work in an exe, when I try it in a cdylib I get linkage errors coming from the C++ compiler (the C++ functions cannot be found).

For example I have a class:

            class MyClass
            {
            public:
                MyClass();
                uint32_t something(uint32_t input) const;
                ...
           }

and on the rust side, I have:

mod ffi {
    unsafe extern "C++" {
        include!("myclass.h");
        type MyClass;
        
        fn new_cxx_test() -> UniquePtr<MyClass>;
        fn exec(&self, t: u32 ) -> u32;
    }
}

When I compile this, I get a link failure (trimmed down a bit):

cxx-bridge.lib(lib.rs.o) : error LNK2019: unresolved external symbol "public: unsigned int __cdecl com::my::area::MyClass::exec(unsigned int)const " (?exec@MyClass@area@my@com@@QEBAII@Z) referenced in function com$my$area$cxxbridge1$MyClass$exec
 
cxx-bridge.lib(lib.rs.o) : error LNK2019: unresolved external symbol "class std::unique_ptr<class com::my::area::MyClass,struct std::default_delete<class com::my::area::MyClass> > __cdecl com::my::area::new_cxx_test(void)" (?new_cxx_test@area@my@com@@YA?AV?$unique_ptr@VMyClass@area@my@com@@U?$default_delete@VMyClass@area@my@com@@@std@@@std@@XZ) referenced in function com$my$area$cxxbridge1$new_cxx_test

 C:\source\mytest.dll : fatal error LNK1120: 2 unresolved externals

@dtolnay
Copy link
Owner

dtolnay commented Oct 20, 2022

I don't know anything about cdylib on Windows, but possibly it's related to #231. Is the error any different if you do this?

class MyClass {
public:
  __declspec(dllexport) MyClass();
  __declspec(dllexport) uint32_t something(uint32_t input) const;
};

@dtolnay dtolnay added the linking Issues that manifest as link failures label Oct 20, 2022
@vpopescu
Copy link
Author

vpopescu commented Oct 20, 2022

I did not see any difference in the message when __declspec(dllexport) was added. I will keep trying a few permutations. The *.lib file seems correct, but I'm no expert. Incidentally it also fails as a dylib, but not as an rlib.

Also, as an observation, I tried to add a block like this in my cpp *.h file:

#ifdef CXX_DLL
# define EXPORT __declspec(dllexport)
#else
# define EXPORT __declspec(dllimport)
#endif

and then in the *.cpp file, I added the following before the header file is included

#define CXX_DLL 1

However it seems like somewhere in the process of building the DLL, the header file is being read directly, and it compiles it with __declspec(dllimport) instead of __declspec(dllexport) since CXX_DLL is not set.

Will update if I learn anything new.

@dtolnay
Copy link
Owner

dtolnay commented Oct 20, 2022

Sounds good. One other knob that may be fruitful to mess with (if you are using cxx-build / build.rs / Cargo as your build system) is right here:

cxx/gen/build/src/lib.rs

Lines 399 to 403 in 8b7643b

let opt = Opt {
allow_dot_includes: false,
cfg_evaluator: Box::new(CargoEnvCfgEvaluator),
..Opt::default()
};

You can try adding:

cxx_impl_annotations: Some("__declspec(dllexport)".to_owned()),

in that struct to make cxx-build stick a given attribute onto every signature in the generated binding. (Obviously we would expose this in a better way if it turns out to work.)

@vpopescu
Copy link
Author

I managed to get it to work. I don't think it has anything to do with linkage, there is probably something I don't understand in the sample. The root of the problem was probably a misunderstanding between my header file, and the code that was generated by the build crate from the cpp file. Once I managed to fix that, it works. I did not have to use the explicit export annotations.

The part I don't understand is this (from sample):

#include "demo/include/blobstore.h"
#include "demo/src/main.rs.h"
#include <algorithm>
...

In my case, I cannot include both "blobstore.h" (or my equivalent thereof) and "main.rs.h" because I end up with redefinition errors. I must be missing something very basic in the sample. I had to comment out main.rs.h (or in my case, lib.rs.h) to get it to compile.

Anyway, sorry for the false alarm, you can close this as "user error" or something. ;)

@dtolnay
Copy link
Owner

dtolnay commented Oct 20, 2022

I cannot include both "blobstore.h" (or my equivalent thereof) and "main.rs.h" because I end up with redefinition errors.

Missing a #pragma once in your header maybe?

@vpopescu
Copy link
Author

No, it's there, but I probably just don't understand the flow here, what causes the conflict below, why those two would conflict.

[... ]\plugin_cxx\src\cxx\defs.h(22): error C2011: '_Manifest': 'struct' type redefinition
[...]\build\plugin_cxx-f864598f2490960a\out\cxxbridge\crate\plugin_cxx/src/cxx/defs.h(21): note: see declaration of '_Manifest'

I have a declaration such as this in my defs.h:

typedef struct __Manifest
{
  //...
} Manifest, *PManifest;

@dtolnay
Copy link
Owner

dtolnay commented Nov 8, 2022

It's unlikely there is any more guidance I would be able to provide on this, so I'll close the issue at this point. Good luck!

@dtolnay dtolnay closed this as completed Nov 8, 2022
@dtolnay dtolnay added the support label Nov 8, 2022
@dtolnay dtolnay changed the title does it work in a cdylib? does it work in a Windows cdylib? Nov 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
linking Issues that manifest as link failures support
Projects
None yet
Development

No branches or pull requests

2 participants