juliainterop / objectivec.jl Goto Github PK
View Code? Open in Web Editor NEWObjective-C embedded in Julia
License: Other
Objective-C embedded in Julia
License: Other
Was removed as part of #11 (due to bitrot), so if anybody is interested in bringing this back, look at https://github.com/JuliaInterop/ObjectiveC.jl/tree/22118319da1fb7601d2a3ecefb671ffbb5e57012
This is not a real issue. But, it would be helpful for humans if there are git tags and GitHub releases that match the registry. The content in TagBot.yml
is very outdated and not effective.
Seems like an Int
to Bool
conversion stopped working?
_
_ _ _(_)_ | A fresh approach to technical computing
(_) | (_) (_) | Documentation: http://docs.julialang.org
_ _ _| |_ __ _ | Type "help()" for help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 0.4.0-dev+5645 (2015-06-27 21:43 UTC)
_/ |\__'_|_|_|\__'_| | Commit b2e69d0* (6 days old master)
|__/ | x86_64-apple-darwin14.3.0
julia> using ObjectiveC
julia> ObjectiveC.framework("AVFoundation")
ERROR: InexactError()
in convert at bool.jl:6
in loadbundle at /Users/kmsquire/.julia/v0.4/ObjectiveC/src/foundation.jl:31
in framework at /Users/kmsquire/.julia/v0.4/ObjectiveC/src/foundation.jl:37
I wanted to fool around with this for querying camera capabilities (on a Mac) for VideoIO.jl
, since it seems that ffmpeg doesn't have that capability yet.
This commented out line is breaking the Cocoa functionality of the package.
Was it because nsrect
isn't working? I had to definition to this to get it to work:
nsrect(x, y, w, h) =
ccall((:nsmakerect, "cocoa"), Ptr{Void}, (Cfloat, Cfloat, Cfloat, Cfloat),
x, y, w, h)
Doesn't segfault when creating an array of strings as shown in the example (or dict for that matter), but for other objects it crashes.
MWE:
julia> using ObjectiveC, .Foundation, Metal
julia> d = current_device()
<AGXG14CDevice: 0x13c04a800>
name = Apple M2 Max
julia> d isa NSObject
true
julia> a = MTLFence(d)
<IOGPUMetalFence: 0x600002278060>
julia> a isa NSObject
true
julia> NSArray([d,d])
<__NSArrayI 0x6000004481e0>(
<AGXG14CDevice: 0x13c04a800>
name = Apple M2 Max,
<AGXG14CDevice: 0x13c04a800>
name = Apple M2 Max
)
julia> NSArray([a,a])
[36456] signal (11.2): Segmentation fault: 11
in expression starting at REPL[5]:1
objc_msgSend at /usr/lib/libobjc.A.dylib (unknown line)
__NSArrayI_new at /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (unknown line)
Allocations: 5428130 (Pool: 5421602; Big: 6528); GC: 9
objc[36456]: Attempt to use unknown class 0x600000b86130.
[36456] signal (6): Abort trap: 6
in expression starting at REPL[5]:1
__abort_with_payload at /usr/lib/system/libsystem_kernel.dylib (unknown line)
Allocations: 5428130 (Pool: 5421602; Big: 6528); GC: 9
Abort trap: 6
We should look into implementing objc_msgSend_stret
to support functions that return structs.
This might be the cause of issues like JuliaGPU/Metal.jl#338.
Appears to be triggered when an Objective-C message in [ ... ]
is combined with standard Julia syntax. Here's an example (from Julia Version 0.4.0-dev+6527).
julia> using ObjectiveC
julia> @objc [[[NSHost currentHost] localizedName] UTF8String] |> bytestring
ERROR: unsupported or misplaced expression escape
julia> @objc [[[NSHost currentHost] localizedName] UTF8String]
Ptr{Int8} @0x00007f977aec8ea1
Seems to be the escape called here: https://github.com/one-more-minute/ObjectiveC.jl/blob/c1a38e9ba01ffc645c64eec75413e4432f2d5083/src/syntax.jl#L32. But I don't know how to debug further.
(This is pretty nifty, BTW.)
While mucking about with how to do some GUI stuff for Julia on OSX, while I was having issues with ObjectiveC.jl, I've managed, somehow bending metaprogramming to my will, to come up with a macro version of objc_msgSend() with multiple args that doesnt rely on ccal(), and should produce a ccall() with no runtime overhead.
Maybe ObjectiveC.jl can benefit from this voodoo.
Its curious to note that
UP = (P...,U...)
ccallTypes = parse("$UP")
works in the REPL, if U,P are set to the appropriate datatype-tuples, and produce the same s-expr as
UU = parse("$U")
PP = parse("$P")
Expr(PP.head, PP.args..., UU.args...)
but not when put in the body of the macro, which generates a useless error.
Alas, this works:
# functions binding objc runtime
function SEL(aString::Union{ASCIIString,UTF8String})
ccall(:sel_getUid, Ptr{Void}, (Ptr{UInt8},), aString)
end
# this objc_msgSend taken from Tk.jl
objc_msgSend{T}(id, uid, ::Type{T}=Ptr{Void}) = ccall(:objc_msgSend, T, (Ptr{Void}, Ptr{Void}), id, SEL(uid))
macro objc_msgSend(T, U, id, methodName::Union{ASCIIString,UTF8String}, args...)
# the objc_msgSend types for self and selector
P = (Ptr{Void},Ptr{Void})
# re-parse the stringified type declarations
UU = parse("$U")
PP = parse("$P")
# manually merge tuples
ccallTypes = Expr(PP.head, PP.args..., UU.args...)
# conatenating U and P via (P...,U...) does not seem to work in macro world (julia v0.4.1)
rval = :(ccall(:objc_msgSend, $T, $ccallTypes, $id, SEL($methodName), $(args...)))
# rval = Expr(:call, :ccall, :(:objc_msgSend), T, ccallTypes, id, :(SEL($methodName)), args...)
# @show rval
# println("\nsexpr(rval)")
# Meta.show_sexpr(rval)
# println("")
return rval
end
# void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...)
function objc_msgSend_stret{T}(self, methodName, ::Type{T})
rval = T()
ccall(:objc_msgSend_stret, Void, (Ptr{T}, Ptr{Void}, Ptr{Void}), Ref(rval), self, SEL(methodName))
return rval
end
usage like so:
function objcString(aString::Union{ASCIIString,UTF8String})
oString = objc_msgSend(objc_getClass("NSString"), "alloc")
oString = @objc_msgSend(Ptr{Void}, (Ptr{UInt8},), oString, "initWithUTF8String:", aString)
oString = objc_msgSend(oString, "autorelease")
return oString
end
This issue is used to trigger TagBot; feel free to unsubscribe.
If you haven't already, you should update your TagBot.yml
to include issue comment triggers.
Please see this post on Discourse for instructions and more details.
If you'd like for me to do this for you, comment TagBot fix
on this issue.
I'll open a PR within a few hours, please be patient!
Something that may be worth discussing: in a8c859f I decided to 'split' the Julia class definitions we generate with
@objcwrapper
(a helper macro to generate object classes) into two: an abstract class to implement the hierarchy, and a concrete one that contains the object pointer. The motivation here is that Objective-C has multilevel inheritance, e.g.,MTLEvent <: NSObject
is a perfectly valid object, but there's alsoMTLSharedEvent <: MTLEvent
which augmentsMTLEvent
. We can't express that in Julia, lacking concrete inheritance, and the traditional alternatives (composition instead of inheritance) break dispatch.After a8c859f, we have
MTLEvent
be an abstract class so thatMTLSharedEvent
can inherit from it, and objects will be put in theMTLEventInstance
orMTLSharedEventInstance
types, depending on the requested type. To make this all invisible, I generate a pseudo constructor for the abstract classes (so callingMTLEvent(ptr::id)
will give anMTLEventInstance
). Case in point, the change did not break the WIP wrappers I have over in JuliaGPU/Metal.jl#117, yet it did allow me to remove the 'fake'MTLAbstractEvent
class I had introduced there. So this looks like a potentially interesting solution for supporting Objective-C's object model (although I may still be missing things, as I'm not really familiar with the language yet and am just designing things in function of the Metal APIs).I also considered making everything an
Object{T}
, but that would make methods ugly (e.g.,foo(obj::Object{<:MTLEvent})
instead of now simplyfoo(obj::MTLEvent)
).
I faced this challenge in Gtk.jl and ended up doing something similar to this, with GObject
and GObjectLeaf
(making the interface the easier type, similar to Ref
vs. Base.RefValue
). I was never quite satisfied with this though, as it felt awkward, led to excess specialization, was a bit hard to extend in disjoint packages, and never quite mapped properly between the type systems (since calling interface methods requires an explicit type cast in the Julia Gtk.jl wrapper). If I was to revisit that decision, I might have gone with a runtime-traits-based approach instead, perhaps with optional mixins.
mutable struct GObject{Mixin}
classid::Int # or encoded in gptr
gptr::Ptr{Cvoid}
mixins::Mixin
end
Then at runtime, it would be sufficient to do the reflection calls needed to decide if a particular interface was applicable, and perhaps also to provide a custom dispatch table hook for places where it is required. This would have let it provide all of the features (multiple inheritance, concrete inheritance, interfaces with inheritance) that are not viable normally.
Secondly, with the current approach, I think I should have at least implemented many convert-trait methods, and coded them up to be visible to reflection:
abstract type AnyInterface; end
abstract type AnyObject; end
struct Interface{T} <: AnyInterface; obj::T; end
inherits_from(::Type, ::Type) = false
inherits_from(::Type{<:Interface}, ::Type{<:Abstract}) = true
convert(::Type{I}, obj::AnyObject) where {I<:AnyInterface} = I(obj)
then when I auto-generated interface calls such as label
, I could also auto-generate dispatch methods that try to select the best matching ccall:
struct HasLabel{T} <: AnyInterface; obj::T; end
label(obj::HasLabel) = ccall
function label(obj)
inherits_from(HasLabel, obj) && return label(HasLabel(obj))
throw(InterfaceMissingError(label, obj))
end
Originally posted by @vtjnash in #11 (comment)
On Julia v0.3.11 or greater, putting the following into the command line produces an error:
julia> using ObjectiveC
julia> @classes NSSound
ERROR: Couldn't find class NSSound
in error at ./error.jl:21
in call at /Users/rje/.julia/v0.5/ObjectiveC/src/primitives.jl:46
julia> using ObjectiveC, Cocoa
ERROR: Cocoa not found
in require at loading.jl:47
Please note, this occurs after adding the change in my accompanying pull request.
I am not sure if this is because my Mac is not properly configured, something changed with recent Mac updates, or something changed in Julia.
Best,
Rob
In my ScriptingBridge project, some properties are SBElementArray
s where the element type is known. I don't think there's a way right now to map that, correct? At least variations of @objcwrapper MyArray{T<:Integer} <: NSArray
don't work. Would be nice to have something like that, because currently I have to manually reinterpret the id{NSObject}
s to what I know they really are.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.