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

Cross-dynamic library compatibility #9

Closed
kamrann opened this issue May 30, 2022 · 6 comments
Closed

Cross-dynamic library compatibility #9

kamrann opened this issue May 30, 2022 · 6 comments

Comments

@kamrann
Copy link

kamrann commented May 30, 2022

Sorry to flood you with issues ;)
This one might be a killer for me on my current project unfortunately; though it's probably not all that surprising, and is not really an issue per-se since this stuff lies outside of the core C++ language.

I'm getting failing any_casts, and I suspect it's caused by putting a value into an any in one dll, and then trying to extract it within another. I guess the comparison on the vtable_ptr is the culprit, since presumably each dll has its own copy of the instantiated vtable_for template, thus incompatible addresses? My suspicion is this is something that there's really no viable solution for, but maybe you have some ideas for a workaround?

Very similar issue with this library, some relevant info in that thread.

@kelbon
Copy link
Owner

kelbon commented May 30, 2022

I think problem is because you compile it separatelly, so one any type has two different vtable pointers
You can try to explicitly instanciate all of needed any s like

template struct aa::any<CRTP, aa::copy, aa::move>;
...

Compile it and link to all other parts.

@kamrann
Copy link
Author

kamrann commented May 30, 2022

I had the same idea (actually I tried explicit instantiation of aa::vtable_for), MSVC ICEd so I gave up ;)

Though it occurred to me that this comparison is actually only required to enable the bad cast exception. It might be nice if you were able to add an 'unsafe' version/overload for any_cast which simply omitted this check and was UB in the case of type mismatch. That way, it's possible to do what I'm trying, and it's on me if I screw things up!

Long term though, I think I should just find a way to avoid passing things over dll boundaries. It's too troublesome in general.

@kelbon
Copy link
Owner

kelbon commented Jun 1, 2022

Though it occurred to me that this comparison is actually only required to enable the bad cast exception. It might be nice if
you were able to add an 'unsafe' version/overload for any_cast which simply omitted this check and was UB in the case of type mismatch. That way, it's possible to do what I'm trying, and it's on me if I screw things up!

Another way is to store name of type in vtable and compare names, not pointer to vtable. But it seems too heavy for default behavior

@kelbon
Copy link
Owner

kelbon commented Jun 8, 2022

I had the same idea (actually I tried explicit instantiation of aa::vtable_for), MSVC ICEd so I gave up ;)

Though it occurred to me that this comparison is actually only required to enable the bad cast exception. It might be nice if you were able to add an 'unsafe' version/overload for any_cast which simply omitted this check and was UB in the case of type mismatch. That way, it's possible to do what I'm trying, and it's on me if I screw things up!

Long term though, I think I should just find a way to avoid passing things over dll boundaries. It's too troublesome in general.

Hi again, can you check if this solves your problems?
#10
#define AA_DLL_COMPATIBLE before include anyany.hpp header and check
(better to use clang-cl in VS studio if you get internal compiler error on MSVC)
image

@kelbon kelbon closed this as completed Jun 19, 2022
@kamrann
Copy link
Author

kamrann commented Jun 22, 2022

Sorry for the delay. Just tested now, and yes, this fixes the issue in my case. Though I wonder what guarantees this can give (for example, compiling one dll with MSVC and another with Clang-cl. Considered ABI-compatible, but not sure that would extend to type names? I'm not suggesting you should worry about that, I completely agree that your default implementation is good. But I think even with this option available, I'd still prefer to just be able to do an unsafe_any_cast, and not have to take the string comparison overhead hit unnecessarily for all dll-internal casts.

Somewhat related to that, I'd suggest considering to drop the any == nullptr check, make it a precondition, and add the check to any_cast(U*) instead. Perhaps the compiler optimizes this away for the reference overload in practice, but still it feels superfluous to be checking there always.

@kelbon
Copy link
Owner

kelbon commented Jun 22, 2022

I'm currently working on some things that will improve the situation, the current support is more like showing an opportunity. Performance will also be improved and there will be a polymorphic pointer and reference type that does not own the content, they are easier to pass through interfaces, and the pointer will have a method that returns a raw pointer to value, so you can do an unsafe cast

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

2 participants