.h discovery process

11 views
Skip to first unread message

Preston Holmes

unread,
Aug 10, 2009, 12:42:02 PM8/10/09
to pymac...@googlegroups.com
A couple weeks ago while on a week off, I spent a little time exploring wrapping OS X C functions in a python library.

Somewhat new territory to me on a number of fronts.

I'm attempting to write a python wrapper for ACLs using sys/acl.h

The two examples I could find on this were:

FSRemoveInheritedACEs

which uses coreservices to get the FS security info object to attach the ACLs to

and

acl_api_fragment

which uses more straight posix C code

both of these include headers, which in turn include other headers etc

gcc seems to have no problem following a chain of include statements, so that all defs are loaded when needed by the compiler.

I was using cython for this attempt, and found a handy script called xml2cython which uses gccxml to convert headers to cython's ctypedef declarations.

You still had to be pretty explicit about what headers you fed it (the script didn't seem to recurse)

and in the end it generates more output then you will need in the final cython code and has to be sorted and cleaned up.

basically a pretty tortuous process.

What are others using for their workflow in attempting this kind of thing - is there a better way or is it just a slog.

I'm trying to do the right thing and write direct to the system functions, but I also know that I could parse the output of ls -le and wrap chmod and get much of what I want.

I'd really like to see that as a library though for speed.

-Preston

SABRE Robotics

unread,
Aug 12, 2009, 11:37:58 AM8/12/09
to pymac...@googlegroups.com
Is there an objective-c wrapper for the functions you want to get at?

Just last night, I figured out I could get at the private framework for the Directory Services Objective-C Wrapper:

from AppKit import *
from Foundation import *
import objc

framework="/System/Library/PrivateFrameworks/DSObjCWrappers.framework"
objc.loadBundle("DSObjCWrapper", globals(), framework)

After I do that, I can access the classes defined in the framework (undocumented source is available at http://www.opensource.apple.com/source/DSTools/DSTools-112.1/ and http://www.opensource.apple.com/tarballs/DSTools/DSTools-112.1.tar.gz).

A real simple program continues:

print "Your local directory contains the following directory nodes:"
directory = DSoDirectory.alloc().initWithLocal()
for name in directory.findNodeNames():
print " - " + name


This is especially nice to use with ipython, as, once you've loaded the bundle, you get the (introspected?) tab completions for methods.


Clinton

Preston Holmes

unread,
Aug 12, 2009, 12:11:17 PM8/12/09
to pymac...@googlegroups.com

On Aug 12, 2009, at 8:37 AM, SABRE Robotics wrote:

> Is there an objective-c wrapper for the functions you want to get at?

Not that I could find in the apple provided frameworks

At least a search for "ACL" only turns up the examples related to
identity services (generic ACL not FS ACL), AFP, or the listed C
examples

It would be relatively straightforward to write an ObjC wrapper - but
that seems a bit much to do that just for a python bridge wrapper...

-Preston

Chris Adams

unread,
Aug 12, 2009, 3:23:56 PM8/12/09
to pymac...@googlegroups.com
On Mon, Aug 10, 2009 at 12:42 PM, Preston Holmes<sanroq...@gmail.com> wrote:
> I'm trying to do the right thing and write direct to the system functions,
> but I also know that I could parse the output of ls -le and wrap chmod and
> get much of what I want.
> I'd really like to see that as a library though for speed.

This is always a balancing act, particularly given the obscure nature
of some of the APIs. In cases like what you're describing I've
resorted to using ctypes since that lets me avoid compiling C objects
but still allows me to pretty directly translate C code and extend it.
In the case of the Keychain APIs a local spotlight search works for
the basic info but I had to resort to http://google.com/codesearch in
several places to find working code since the documentation provided
little of value.

The downside to the ctypes approach is that you won't see anything
which only exists as a C define - you can either duplicate those in
Python (e.g. http://code.google.com/p/pymacadmin/source/browse/lib/PyMacAdmin/Security/__init__.py)
or simply write a little throwaway C program which printfs the value
you need if it's something which isn't generally useful.

Chris

Preston Holmes

unread,
Aug 12, 2009, 4:39:00 PM8/12/09
to pymac...@googlegroups.com

On Aug 12, 2009, at 12:23 PM, Chris Adams wrote:

> The downside to the ctypes approach is that you won't see anything
> which only exists as a C define

This was the case for acl.h

I don't think it is available in any compiled framework library

But I'm not really sure how I would verify that for certain

-P


SABRE Robotics

unread,
Aug 12, 2009, 6:34:31 PM8/12/09
to pymac...@googlegroups.com

I'm wondering how to supply a char* argument to something from
PyObjC. [ My full question is at http://stackoverflow.com/questions/1268667/call-a-selector-that-takes-a-char-from-pyobjc
; with that and getting a "Tumbleweed" badge on my last PyObjC
question ( http://stackoverflow.com/questions/1229830/error-drawing-text-on-nsimage-in-pyobjc
), I'm starting to think that Stack Overflow isn't a great place for
PyObjC questions.]

Basically, I'm trying to call a function that has a selector defined as:

- (BOOL) hasRecordsOfType:(const char*) inType

and PyObjC doesn't know to change the string I supply it into a char
*. Using ctypes sounded interesting. I just tried:

node
.hasRecordsOfType_(ctypes.c_char_p('dsRecTypeStandard:ComputerLists'))

but get

ValueError: depythonifying 'char', got 'c_char_p'


Clinton

SABRE Robotics

unread,
Aug 12, 2009, 6:56:24 PM8/12/09
to pymac...@googlegroups.com
I doubt this'll help, but if you suspect it is included in a private framework, you might find http://lipidity.com/apple/exposing-those-private-frameworks/ to be of value.  

You might also try this:

find /System/Library/PrivateFrameworks -type f -perm -o+rx -exec strings {} \; | grep -i acl

That'll look for the word "acl" inside of all the function names of all the private frameworks on your system.  Try it on both the Private and regular frameworks.  You may want to redirect it to a file instead of piping it through grep.

Cheers,
Clinton


Preston Holmes

unread,
Aug 12, 2009, 7:40:01 PM8/12/09
to pymac...@googlegroups.com
I'm not in my strong suit here - but I think that PyObjC doesn't know
about ctypes types

In otherwords, you can't mix and match them

you might try calling into your framework with just ctypes

See the ctypes examples in the pymacadmin project

-Preston

Preston Holmes

unread,
Aug 12, 2009, 7:48:57 PM8/12/09
to pymac...@googlegroups.com

On Aug 12, 2009, at 3:34 PM, SABRE Robotics wrote:

>
>
what about using nsstrings cStringUsingEncoding: ?

It is supposed to take a string and return char *

-P

>
>
> Clinton
>
> >

SABRE Robotics

unread,
Aug 12, 2009, 9:16:37 PM8/12/09
to pymac...@googlegroups.com

On 12-Aug-09, at 5:48 PM, Preston Holmes wrote:

node
.hasRecordsOfType_(ctypes.c_char_p('dsRecTypeStandard:ComputerLists'))

but get

ValueError: depythonifying 'char', got 'c_char_p'

what about using nsstrings cStringUsingEncoding: ?

It is supposed to take a string and return char *

-P

That's an excellent idea.  In testing it, though, I get the same result as before:

y = node.hasRecordsOfType_( NSString.stringWithString_('dsRecTypeStandard:ComputerLists').cStringUsingEncoding_(1) )
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

/Users/clinton/Development/Work/AccountSync/<ipython console> in <module>()

ValueError: depythonifying 'char', got 'str' of 31



Clinton

SABRE Robotics

unread,
Aug 17, 2009, 2:29:53 PM8/17/09
to pymac...@googlegroups.com
Preston,

take a look at the man page for gen_bridge_metadata.  It is designed to create files to help languages using Objective-C bridge support to call into functions in a framework (although my attempt as using it for a private framework failed), but, at the end, it has this example:

     It is also possible to generate bridge support metadata for a standalone
     C library (here, libcurl):
           gen_bridge_metadata -c '-lcurl -I/usr/include/curl'
           /usr/include/curl/*.h > /Library/BridgeSupport/curl.bridgesupport


Cheers,
Clinton

On 10-Aug-09, at 10:42 AM, Preston Holmes wrote:

Reply all
Reply to author
Forward
0 new messages