Professional Web Applications Themes

Carbon and Mach-O? - Mac Programming

I've been told that to have an OSX application that accesses USB ports I have to have a Mach-O application. Does this mean that I have lost all access to carbon functionality? I have imported my carbon source code into a Codewarrior template for a Mach-O appliction, but when I try to build it tells me it cannot open the carbon headers like "Events.h", "Dialog.h", "Files.h", etc. Is the carbon toolbox off limits for a Mach-O application? I've not yet found a decent explanation of Mach-O beyond its description as the UNIX programming language on which OSX is based. I ...

  1. #1

    Default Carbon and Mach-O?

    I've been told that to have an OSX application that accesses USB ports I
    have to have a Mach-O application.

    Does this mean that I have lost all access to carbon functionality?

    I have imported my carbon source code into a Codewarrior template for a
    Mach-O appliction, but when I try to build it tells me it cannot open
    the carbon headers like "Events.h", "Dialog.h", "Files.h", etc.

    Is the carbon toolbox off limits for a Mach-O application?

    I've not yet found a decent explanation of Mach-O beyond its description
    as the UNIX programming language on which OSX is based.

    I guess I don't fully understand how Carbon and Mach-O relate to each
    other, if at all.

    Can a Carbon application access USB ports using Mach-O code like that
    contained in the IOKit?

    If not, what toolbox methods ARE used in applications that access
    hardware like firewire devices and USB devices?

    CT
    Charles Guest

  2. #2

    Default Re: Carbon and Mach-O?

    In article <doit.wisc.edu>,
    Charles Thomas <facstaff.wisc.edu> wrote:
     

    1.) Learn to crosspost. (put more than one newsgroup on the Newsgroup:
    line of your news posting program, so that when we read newsgroups we'll
    see your posting only once. (our newsreaders keep track.)

    2.) It isn't USB, but here is some sample code I use to get at serial
    ports from CFM under OS X. It uses some IOKit, so you can see how, at
    run time, I connect to Mach-O libraries from my CFM program, and
    extract the funtion pointers I need.:

    #include <fcntl.h>
    #include <termios.h>

    typedef int (*ErrnoProc)(void);
    typedef int (*OpenProc)(const char *path, int flags);
    typedef int (*CloseProc)(int);
    typedef int (*FcntlProc)(int fd, int cmd, int arg);
    typedef int (*ReadProc)(int d, void *buf, size_t nbytes);
    typedef int (*WriteProc)(int d, const void *buf, size_t nbytes);
    typedef int (*IoctlProc)(int d, unsigned long request, char *argp);
    typedef int (*TcdrainProc)(int fd);
    typedef int (*TcgetattrProc)(int fd, struct termios *t);
    typedef int (*TcsetattrProc)(int fd, int action, const struct termios *t);
    typedef int (*CfsetspeedProc)(struct termios *t, speed_t speed);
    typedef void (*CfmakerawProc)(struct termios *t);

    typedef long kern_return_t;
    typedef unsigned int mach_port_t;
    typedef mach_port_t io_object_t;
    typedef io_object_t io_iterator_t;
    typedef io_object_t io_registry_entry_t;
    typedef UInt32 IOOptionBits;

    typedef kern_return_t (*IOMasterPortProc)( mach_port_t bootstrapPort, mach_port_t *masterPort);
    typedef kern_return_t (*IOObjectReleaseProc)(io_object_t);
    typedef io_iterator_t (*IOIteratorNextProc)(io_iterator_t);
    typedef kern_return_t (*IOServiceGetMatchingServicesProc)(mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t *existing);
    typedef CFMutableDictionaryRef (*IOServiceMatchingProc)(const char * name);
    typedef CFTypeRef (*IORegistryEntryCreateCFPropertyProc)(io_registry _entry_t entry, CFStringRef key, CFAllocatorRef allocator, IOOptionBits options);


    static ErrnoProc errnop;
    static OpenProc openp;
    static CloseProc closep;
    static FcntlProc fcntlp;
    static ReadProc readp;
    static WriteProc writep;
    static IoctlProc ioctlp;
    static TcdrainProc tcdrainp;
    static TcgetattrProc tcgetattrp;
    static TcsetattrProc tcsetattrp;
    static CfsetspeedProc cfsetspeedp;
    static CfmakerawProc cfmakerawp;

    static IOMasterPortProc ioMasterPort;
    static IOServiceMatchingProc ioServiceMatching;
    static IOObjectReleaseProc ioObjectRelease;
    static IOIteratorNextProc ioIteratorNext;
    static IOServiceGetMatchingServicesProc ioServiceGetMatchingServices;
    static IORegistryEntryCreateCFPropertyProc ioRegistryEntryCreateCFProperty;

    #ifndef Length_
    #define Length_(s) ((int) (unsigned) ((s)[0]))
    #endif

    static short Min(short a, short b){ return a < b ? a : b; }


    // ---------------------------------------------------------------------------
    // StrMove
    // ---------------------------------------------------------------------------
    /// StrMove - copy a pascal string from src to dest

    static void StrMove(ConstStringPtr src, StringPtr dest){
    BlockMoveData(src, dest, Length_(src) + 1);
    }

    // ---------------------------------------------------------------------------
    // Concat
    // ---------------------------------------------------------------------------

    static void Concat(StringPtr s, ConstStringPtr tail){
    short newLen;

    newLen = Min(255, Length_(s) + Length_(tail));
    BlockMoveData((Ptr) &tail[1] ,(Ptr) &s[1+Length_(s)], newLen - Length_(s));
    s[0] = newLen;
    }

    // ---------------------------------------------------------------------------------
    // LoadFrameworkBundle
    // ---------------------------------------------------------------------------------
    /// This routine finds a the named framework and creates a CFBundle
    /// object for it. It looks for the framework in the frameworks folder,
    /// as defined by the Folder Manager. Currently this is
    /// "/System/Library/Frameworks", but we recommend that you avoid hard coded
    /// paths to ensure future compatibility.
    ///
    /// You might think that you could use CFBundleGetBundleWithIdentifier but
    /// that only finds bundles that are already loaded into your context.
    /// That would work in the case of the System framework but it wouldn't
    /// work if you're using some other, less-obvious, framework.

    static OSStatus LoadFrameworkBundle(CFStringRef framework, CFBundleRef *bundlePtr)
    {
    #if CALL_NOT_IN_CARBON
    #pragma unused(framework, bundlePtr)
    return paramErr;
    #else
    OSStatus err;
    FSRef frameworksFolderRef;
    CFURLRef baseURL;
    CFURLRef bundleURL;

    *bundlePtr = NULL;

    baseURL = NULL;
    bundleURL = NULL;

    // Find the frameworks folder and create a URL for it.

    err = FSFindFolder(kOnAppropriateDisk, kFrameworksFolderType, true, &frameworksFolderRef);
    if (err == noErr) {
    baseURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &frameworksFolderRef);
    if (baseURL == NULL) {
    err = coreFoundationUnknownErr;
    }
    }

    // Append the name of the framework to the URL.

    if (err == noErr) {
    bundleURL = CFURLCreateCopyAppendingPathComponent(kCFAllocator SystemDefault, baseURL, framework, false);
    if (bundleURL == NULL) {
    err = coreFoundationUnknownErr;
    }
    }

    // Create a bundle based on that URL and load the bundle into memory.
    // We never unload the bundle, which is reasonable in this case because
    // the sample assumes that you'll be calling functions from this
    // framework throughout the life of your application.

    if (err == noErr) {
    *bundlePtr = CFBundleCreate(kCFAllocatorSystemDefault, bundleURL);
    if (*bundlePtr == NULL) {
    err = coreFoundationUnknownErr;
    }
    }
    if (err == noErr) {
    if ( ! CFBundleLoadExecutable( *bundlePtr ) ) {
    err = coreFoundationUnknownErr;
    }
    }

    // Clean up.

    if (err != noErr && *bundlePtr != NULL) {
    CFRelease(*bundlePtr);
    *bundlePtr = NULL;
    }
    if (bundleURL != NULL) {
    CFRelease(bundleURL);
    }
    if (baseURL != NULL) {
    CFRelease(baseURL);
    }

    return err;
    #endif
    }

    #define reinterpret_cast_(aType) (aType)

    // ---------------------------------------------------------------------------
    // InitFuncPointers
    // ---------------------------------------------------------------------------
    /// InitFuncPointers - initialize our dynamicly loaded function pointers to system calls.

    static OSStatus InitFuncPointers(void){
    OSStatus err = noErr;
    if(NULL == ioMasterPort){
    CFBundleRef ioKitBundle;
    CFBundleRef sysBundle;
    if (noErr == err) {
    err = LoadFrameworkBundle(CFSTR("IOKit.framework"), &ioKitBundle);
    }
    if (noErr == err) {
    ioMasterPort = reinterpret_cast_(IOMasterPortProc)(CFBundleGetFun ctionPointerForName(ioKitBundle, CFSTR("IOMasterPort")));
    ioServiceMatching = reinterpret_cast_(IOServiceMatchingProc)(CFBundleG etFunctionPointerForName(ioKitBundle, CFSTR("IOServiceMatching")));
    ioObjectRelease = reinterpret_cast_(IOObjectReleaseProc)(CFBundleGet FunctionPointerForName(ioKitBundle, CFSTR("IOObjectRelease")));
    ioIteratorNext = reinterpret_cast_(IOIteratorNextProc)(CFBundleGetF unctionPointerForName(ioKitBundle, CFSTR("IOIteratorNext")));
    ioRegistryEntryCreateCFProperty = reinterpret_cast_(IORegistryEntryCreateCFPropertyP roc)(CFBundleGetFunctionPointerForName(ioKitBundle , CFSTR("IORegistryEntryCreateCFProperty")));
    ioServiceGetMatchingServices = reinterpret_cast_(IOServiceGetMatchingServicesProc )(CFBundleGetFunctionPointerForName(ioKitBundle, CFSTR("IOServiceGetMatchingServices")));
    }
    if(noErr == err){
    err = LoadFrameworkBundle(CFSTR("System.framework"), &sysBundle);
    }
    if(noErr == err){
    // see: errno.h in the System framework for the reasoning behind the next line
    errnop = reinterpret_cast_(ErrnoProc)(CFBundleGetFunctionPo interForName(sysBundle, CFSTR("__error")));
    openp = reinterpret_cast_(OpenProc)(CFBundleGetFunctionPoi nterForName(sysBundle, CFSTR("open")));
    closep = reinterpret_cast_(CloseProc)(CFBundleGetFunctionPo interForName(sysBundle, CFSTR("close")));
    fcntlp = reinterpret_cast_(FcntlProc)(CFBundleGetFunctionPo interForName(sysBundle, CFSTR("fcntl")));
    readp = reinterpret_cast_(ReadProc)(CFBundleGetFunctionPoi nterForName(sysBundle, CFSTR("read")));
    writep = reinterpret_cast_(WriteProc)(CFBundleGetFunctionPo iterForName(sysBundle, CFSTR("write")));
    ioctlp = reinterpret_cast_(IoctlProc)(CFBundleGetFunctionPo interForName(sysBundle, CFSTR("ioctl")));
    tcdrainp = reinterpret_cast_(TcdrainProc)(CFBundleGetFunction PointerForName(sysBundle, CFSTR("tcdrain")));
    tcgetattrp = reinterpret_cast_(TcgetattrProc)(CFBundleGetFuncti onPointerForName(sysBundle, CFSTR("tcgetattr")));
    tcsetattrp = reinterpret_cast_(TcsetattrProc)(CFBundleGetFuncti onPointerForName(sysBundle, CFSTR("tcsetattr")));
    cfsetspeedp = reinterpret_cast_(CfsetspeedProc)(CFBundleGetFunct ionPointerForName(sysBundle, CFSTR("cfsetspeed")));
    cfmakerawp = reinterpret_cast_(CfmakerawProc)(CFBundleGetFuncti onPointerForName(sysBundle, CFSTR("cfmakeraw")));
    }

    }
    return err;
    }

    // ---------------------------------------------------------------------------
    // InitSerialPortArray
    // ---------------------------------------------------------------------------

    #define MACH_PORT_NULL 0
    #define kIOSerialBSDServiceValue "IOSerialBSDClient"
    #define kIOSerialBSDTypeKey "IOSerialBSDClientType"
    #define kIOSerialBSDRS232Type "IORS232SerialStream"
    #define kIOTTYDeviceKey "IOTTYDevice"

    static CarbonSerialPortX ** sH;

    static OSStatus InitSerialPortArray(void){
    OSStatus err = noErr;
    mach_port_t masterPort;
    CFMutableDictionaryRef classesToMatch;
    io_iterator_t serialPortIterator = NULL;
    io_object_t serialService = NULL;
    if(NULL == sH){
    sH = (CarbonSerialPortX **) NewHandle(0);
    }else{
    SetHandleSize((Handle) sH, 0);
    }
    err = (*ioMasterPort)(MACH_PORT_NULL, &masterPort);
    if(noErr == err && NULL == (classesToMatch = (*ioServiceMatching)(kIOSerialBSDServiceValue))){
    err = paramErr;
    }
    if(noErr == err){
    CFDictionarySetValue(classesToMatch,
    CFSTR(kIOSerialBSDTypeKey),
    CFSTR(kIOSerialBSDRS232Type));
    }
    if(noErr == err){ err = (*ioServiceGetMatchingServices)(masterPort, classesToMatch, &serialPortIterator); }

    while (noErr == err && NULL != (serialService = (*ioIteratorNext)(serialPortIterator)))
    {
    CFTypeRef bsdPathAsCFString;
    CarbonSerialPortX port = {0};
    Boolean result;
    bsdPathAsCFString = (*ioRegistryEntryCreateCFProperty)(serialService,
    CFSTR(kIOTTYDeviceKey),
    kCFAllocatorDefault,
    0);
    result = CFStringGetPascalString(bsdPathAsCFString,
    port.userName,
    sizeof port.userName,
    kCFStringEncodingASCII);
    CFRelease(bsdPathAsCFString);
    (*ioObjectRelease)(serialService);
    port.deviceName[0] = 0;
    if('/' != port.userName[1]){
    Concat(port.deviceName, "\p/dev/cu."); // use /dev/cu.* for non-blocking I/O on Keyspan serial port
    //Concat(port.deviceName, "\p/dev/tty."); // /dev/tty.* blocks on I/O
    }
    Concat(port.deviceName, port.userName);
    // append port to the handle of ports.
    port.originalTTYAttrs = (struct termios*) NewPtrClear(sizeof(struct termios));
    err = PtrAndHand(&port, (Handle) sH, sizeof port);
    port.originalTTYAttrs = NULL;
    }
    if(NULL != sH){
    HLock((Handle) sH);
    }

    // clean up
    if(NULL != serialPortIterator){
    OSStatus e = (*ioObjectRelease)(serialPortIterator);
    if(noErr == err){ err = e; }
    }
    if(NULL != masterPort){
    OSStatus e = (*ioObjectRelease)(masterPort);
    if(noErr == err){ err = e; }
    }
    return err;
    }

    // ---------------------------------------------------------------------------
    // DisposeSerialPortArray
    // ---------------------------------------------------------------------------

    static OSStatus DisposeSerialPortArray(void){
    OSStatus err = noErr;
    if(NULL != sH){
    DisposeHandle((Handle) sH);
    sH = NULL;
    }
    return err;
    }

    // ---------------------------------------------------------------------------
    // InitCarbonSerialX
    // ---------------------------------------------------------------------------

    OSStatus InitCarbonSerialX(void){
    OSStatus err = InitFuncPointers();
    if(noErr == err){ err = InitSerialPortArray(); }
    return err;
    }

    // ---------------------------------------------------------------------------
    // CloseIfOpenX
    // ---------------------------------------------------------------------------

    static OSStatus CloseIfOpenX(CarbonSerialPortPtr inP, void * refCon){
    #pragma unused(refCon)
    CloseCarbonSerialPort(inP);
    return noErr;
    }

    // ---------------------------------------------------------------------------
    // DeleteTermios
    // ---------------------------------------------------------------------------

    static OSStatus DeleteTermios(CarbonSerialPortPtr inP, void * refCon){
    #pragma unused(refCon)
    CarbonSerialPortX *p = (CarbonSerialPortX *) inP;
    if(NULL != p->originalTTYAttrs){
    DisposePtr((Ptr) p->originalTTYAttrs);
    p->originalTTYAttrs = NULL;
    }
    return noErr;
    }

    // ---------------------------------------------------------------------------
    // CloseCarbonSerialX
    // ---------------------------------------------------------------------------

    OSStatus CloseCarbonSerialX(){
    WalkCarbonSerialPortsX(CloseIfOpenX, NULL);
    WalkCarbonSerialPortsX(DeleteTermios, NULL);

    return DisposeSerialPortArray();
    }

    // ---------------------------------------------------------------------------
    // SetCarbonSerialPortXBlocking
    // ---------------------------------------------------------------------------

    OSStatus SetCarbonSerialPortXBlocking(CarbonSerialPortX* inP, Boolean isBlocking)
    {
    // See fcntl(2) ("man 2 fcntl") for details.
    int flags = isBlocking ? 0 : O_NONBLOCK;
    OSErr err = (*fcntlp)(inP->refNum, F_SETFL, flags);
    if ( err != noErr && (*errnop)() ) err = (*errnop)();
    return err;
    }

    // ---------------------------------------------------------------------------
    // OpenCarbonSerialPortX
    // ---------------------------------------------------------------------------

    OSStatus OpenCarbonSerialPortX(CarbonSerialPortX* inP){
    char buffer[256];
    OSStatus val = noErr;
    CopyPascalStringToC(inP->deviceName, buffer);
    if(-1 == (inP->refNum = (*openp)(buffer, O_RDWR | O_NOCTTY | O_NONBLOCK))){
    val = (*errnop)();
    }

    // Note that open() follows POSIX semantics: multiple open() calls to the same file will succeed
    // unless the TIOCEXCL ioctl is issued. This will prevent additional opens except by root-owned
    // processes.
    // See tty(4) ("man 4 tty") and ioctl(2) ("man 2 ioctl") for details.
    if(noErr == val && -1 == (*ioctlp)(inP->refNum, TIOCEXCL, 0)){
    val = (*errnop)();
    }

    // Get the current options and save them so we can restore the default settings later.
    if(noErr == val && -1 == (*tcgetattrp)(inP->refNum, inP->originalTTYAttrs)){
    val = (*errnop)();
    }

    // error cleanup.
    if(noErr != val && 0 != inP->refNum){
    (*closep)(inP->refNum);
    inP->refNum = 0;
    }
    return val;
    }

    // ---------------------------------------------------------------------------
    // CloseCarbonSerialPortX
    // ---------------------------------------------------------------------------

    OSStatus CloseCarbonSerialPortX(CarbonSerialPortX* inP){
    if(0 == inP->refNum){
    return noErr;
    }
    // Block until all written output has been sent from the UART.
    // Note that this call is simply passed on to the serial device driver.
    // See tcsendbreak(3) ("man 3 tcsendbreak") for details.
    // We ignore an error here, since it is more important to actually close the port.
    (*tcdrainp)(inP->refNum);
    // Traditionally it is good practice to reset a serial port back to
    // the state in which you found it. This is why the original termios struct
    // was saved. We ignore an error here, since it is more important to actually close the port.
    (*tcsetattrp)(inP->refNum, TCSANOW, inP->originalTTYAttrs);
    if(noErr != (*closep)(inP->refNum)){
    inP->refNum = 0;
    return (*errnop)();
    }
    inP->refNum = 0;
    return noErr;
    }


    // ---------------------------------------------------------------------------
    // ReadCarbonSerialPortX
    // ---------------------------------------------------------------------------

    OSStatus ReadCarbonSerialPortX(CarbonSerialPortX* inP, long *ioLen, void *outBuffer){
    int val;
    if(-1 == (val = (*readp)(inP->refNum, outBuffer, *ioLen))){
    if ( (*errnop)() ) return (*errnop)();
    else return val;
    }
    *ioLen = val;
    return noErr;
    }
    David Guest

  3. #3

    Default Re: Carbon and Mach-O?

    In article <doit.wisc.edu>,
    Charles Thomas <facstaff.wisc.edu> wrote:
     

    Not quite, but Mach-O makes it easier.
     

    Not at all. Carbon applications can be either CFM or Mach-O. Actually,
    many APIs are only directly available from Mach-O (though they can be
    specially imported one at a time in CFM code), so you could argue that
    you have more functionality in Mach-O.
     

    Nope; it's just that Mach-O developer tools use frameworks, while CFM
    developer tools typically use flat headers. You can replace all of your
    Carbon header includes with #include <Carbon/Carbon.h> (i.e. the main
    Carbon framework header). For example, change
    #include <Dialog.h>
    #include <Events.h>
    #include <Files.h>
    to this
    #include <Carbon/Carbon.h>

    Hope this helps,
    Eric

    --
    Eric Albert edu
    http://rescomp.stanford.edu/~ejalbert/
    Eric Guest

  4. #4

    Default Re: Carbon and Mach-O?

    In article <doit.wisc.edu>,
    Charles Thomas <facstaff.wisc.edu> wrote:
     

    Your main questions have already been answered, so I'll pass by those,
    but nobody has really described what Mach-O is, which may be nice to
    know.

    Basically, Mach-O is a file format. All programs come in a particular
    file format, just like any other kind of file. On Linux it's usually
    ELF, on Mac OS 9 it's CFM, and on OS X it's Mach-O.

    Of course, one of the goals of Carbon is to let people make apps that
    run on both OS 9 and OS X, so OS X knows how to handle CFM apps too. The
    trouble is that a library that works for Mach-O won't automatically work
    for CFM apps. So there's a layer that lets you get at Carbon from CFM,
    but not a lot of other things. For stuff like IOKit, you either have to
    access manually (David Oster's post shows how this works) or you have to
    make a Mach-O app.

    Carbon and Mach-O aren't really directly related. Carbon is an API which
    happens to be directly accessable to both Mach-O and CFM apps.
    Michael Guest

Similar Threads

  1. CF and Mach-ii ??
    By weblover in forum Coldfusion - Advanced Techniques
    Replies: 1
    Last Post: July 6th, 03:01 AM
  2. Mach II Framework Questions
    By JakeFlynn in forum Coldfusion - Advanced Techniques
    Replies: 10
    Last Post: June 9th, 12:11 AM
  3. mach-ii opinions and experiences??
    By gumshoe in forum Macromedia ColdFusion
    Replies: 4
    Last Post: March 10th, 04:27 PM
  4. Mach II & URLSessionFormat()
    By monochrome13 in forum Macromedia ColdFusion
    Replies: 0
    Last Post: February 28th, 01:50 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139