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

efficient interface for accessing an external c variable's value #1815

Closed
vtjnash opened this issue Dec 22, 2012 · 10 comments
Closed

efficient interface for accessing an external c variable's value #1815

vtjnash opened this issue Dec 22, 2012 · 10 comments
Assignees

Comments

@vtjnash
Copy link
Member

vtjnash commented Dec 22, 2012

proposed api (new built-in):
cvalue( (:sym, :lib), Type ) :: Type

functionally equivalent to
unsafe_ref( convert( Ptr{T}, dlsym( :sym, dlopen(:lib) ) ) )
but with only the unsafe_ref call occurring at runtime, the rest being converted into a llvm global at compile time (similar to the first argument to ccall)

additionally, another valuable function would be
cexists( (:sym, :lib) ) :: Bool

then I think dlsym/dlopen can be removed from the language?

@JeffBezanson
Copy link
Member

Ok, this seems like a good idea. I used to prefer dlsym but I think I've changed my mind completely.
I would name it cglobal or cvar or maybe csymbol instead though.
Maybe unsafe_ref should not be rolled into it though, so you have the possibility of writing as well. Perhaps just as well not to encourage writing to globals though!

@vtjnash
Copy link
Member Author

vtjnash commented Dec 22, 2012

cglobal sounds good

However, I'm not certain this signature would actually be correct (removing the implicit unsafe_ref call):
cglobal( (:sym, :lib), Type ) :: Ptr{Type}
my concern is that this should actually be a llvm Value* type not an actual pointer. thus it wouldn't get completely resolved until the call to unsafe_ref. putting these together makes that OK since it is entirely compiler details.

to allow unsafe_assign, there could be a optional third parameter that did assignment (and also returned the new value)?

there could be an expectation that, like ccalls, there would be wrapper functions written for common variables
thisvar() = cglobal( (:thisvar, :lib), Type)
thisvar(value) = cglobal( (:thisvar, :lib), Type, value) <-- cconvert will be called automatically on the third parameter

@JeffBezanson
Copy link
Member

Good points.

@StefanKarpinski
Copy link
Member

I woild prefer cvar or cval.

On Friday, December 21, 2012, Jeff Bezanson wrote:

Good points.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1815#issuecomment-11632515.

@ghost ghost assigned vtjnash Feb 2, 2013
@JeffBezanson
Copy link
Member

We should add the following types:

abstract CFunction{R,A<:Tuple}

type NativeSymbol{T}
    name::Symbol
    lib::Symbol
end

This generalizes Ptr, and formalizes the first argument to ccall. To access a variable, you could do unsafe_ref(NativeSymbol{Int32}(:var,:lib)). This would also be what cfunction returns, and there could be a conversion from Function to CFunction.

@stevengj
Copy link
Member

I think you guys are overthinking this.

cglobal( (:sym, :lib), Type=Void ) :: Ptr{Type} seems right to me. If you are accessing a C library, you want low-level access to the pointer. Not only is this the most flexible interface, it is also clearer because it preserves the spirit of the original C interface.

In many cases, you might not even be dereferencing the pointer at all; you might just be passing it to other C API functions. (For example, in the Python API, various Python types, e.g PyInt_Type, are declared as globals, which you then pass to other Python functions as pointers &PyIntType.)

The only other interface I would optionally consider adding would be cconstant(sym, Type ) :: Type, defined by cconstant(sym, Type) = unsafe_load(cglobal(sym, Type)). This is merely a convenience for the common case of global constants that are used by value, rather than by reference. (For example, the GSL API declares various opaque global descriptor pointers which you pass to other API functions, e.g. to indicate algorithms for minimization or root-finding, but cglobal would give you an awkward pointer to the pointer.)

The user can wrap other abstractions on top of a C global if needed.

@JeffBezanson
Copy link
Member

Yes, you're probably right. That interface looks good.

@GunnarFarneback
Copy link
Contributor

I'm not at all certain of the implications of this but I hope it still makes it possible to ccall a C function pointer returned by an earlier ccall.

@stevengj
Copy link
Member

@GunnarFarneback, I don't think ccall will be affected.

@vtjnash
Copy link
Member Author

vtjnash commented May 13, 2013

Ah, that is better. For some reason, I had thought it wouldn't be possible to generate the pointer in a different JIT invokation from its use, so I had proposed something complicated, but this seems to do it.

stevengj added a commit that referenced this issue May 13, 2013
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

5 participants