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

added dynamic library loading via libdl #2598

Closed
wants to merge 5 commits into from

Conversation

emekoi
Copy link
Contributor

@emekoi emekoi commented May 31, 2019

i implemented dynamic library loading for darwin using dlsym. getting errors back is going to be somewhat involved as dlerror only returns strings. i'm also not sure if we should check to see if the library being loaded is compatible with the loading process using dlopen_preflight.

i also fixed a logic errors in the windows code for loading dll's. DynLib.lookup would return 0 instead of null if the symbol couldn't be found.

@LemonBoy
Copy link
Contributor

The dlopen + dlsym is also useful on linux (if linked to libc) & the BSDs... Maybe the struct can be renamed as DlDynlib (since it uses libdl) and reused there?

@emekoi
Copy link
Contributor Author

emekoi commented May 31, 2019

doesn't dlopen/dlsym require libdl on linux? on darwin it's included in libSystem which we unconditionally link to as it's the stable syscall interface.

@andrewrk andrewrk added this to the 0.5.0 milestone Aug 19, 2019
@andrewrk
Copy link
Member

andrewrk commented Sep 3, 2019

@emekoi where did you land with this? If it's ready for merge, would you mind rebasing it and let's try to get that CI light to turn green

@andrewrk andrewrk modified the milestones: 0.5.0, 0.6.0 Sep 3, 2019
@emekoi
Copy link
Contributor Author

emekoi commented Sep 4, 2019

i will try to clean this up and rebase it by the end of the week.

@emekoi
Copy link
Contributor Author

emekoi commented Sep 6, 2019

can anyone think of a way to solve #2435? or would passing a c"..." literal suffice?

pub fn lookup(self: *WindowsDynLib, name: []const u8) ?usize {
if (windows.kernel32.GetProcAddress(self.dll, name.ptr)) |addr| {
return @ptrToInt(addr);
pub fn lookup(self: *WindowsDynLib, comptime T: type, name: []const u8) !?T {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate that this adds the possibility of failure. Maybe there can be lookupC (following the patterns in std.fs.File) which accepts a null_terminated_name: [*]const u8 (this can be changed once #265 is done), and has no possibility of failure. lookup would do this null termination and then call lookupC. Then API users can opt in to using C string literals and have no possibility of failure. (And again after #265 normal string literals would also work.)

Another reasonable way to design this API would be to have lookup accept a comptime max_name_len: usize and use that as the c_name array size. The documentation for the function would say, caller guarantees that name.len <= max_name_len. This pushes the only possible error condition out of lookup and onto the caller.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so if the caller passes an array that's too small they get a buffer overflow?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes in the API I'm proposing, if they don't fulfill the guarantee, it would be undefined behavior in release-small & release-fast, and would trigger runtime safety in debug & release-safe (either in the call to std.mem.copy or the part where it sets the zero). It would be pretty clear at the callsite, because they would be consciously choosing this max_name_len.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about LinuxDynLib? will the lookup function change based on the target?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux dyn lib needs a check for whether we're linking libc or not. If we're linking libc then it's the same API as darwin, I believe. So a cross platform application is limited to this API anyway. The more restrictive API can work on all platforms. However, we can also provide the nicer API for Linux that takes a slice and doesn't fail, and it will be documented as being available under certain conditions, and when those conditions are not met, it will be a compile error. So the programmer has access to a cross platform API which is restricted to the lowest common denominator, as well as target-specific API(s) that have different capabilities but using them means giving up portability. With Zig's comptime logic, we can provide the programmer with all of these options. The path of least resistance should be the cross-platform API.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also to be clear I don't expect you to necessarily do all of this in this PR, I'm just trying to give you the vision.

@andrewrk andrewrk removed this from the 0.6.0 milestone Oct 1, 2019
@daurnimator daurnimator mentioned this pull request Nov 20, 2019
@emekoi emekoi changed the title added dynamic library loading for darwin added dynamic library loading via libdl Dec 8, 2019
@andrewrk andrewrk closed this in 0d99744 Dec 10, 2019
@emekoi
Copy link
Contributor Author

emekoi commented Dec 10, 2019

@andrewrk thanks for merging this

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

Successfully merging this pull request may close these issues.

4 participants