aharren / LibComponentLogging-Core

A small logging library for Objective-C applications (Mac OS X and iPhone OS/iOS) which provides conditional logging based on log levels and log components. Additionally, different logging strategies can be used, e.g. writing log messages to a file or sending them to the system log, while using the same logging interface.
http://0xc0.de/LibComponentLogging
110 stars 11 forks source link

Swift support #28

Closed stefanfisk closed 6 months ago

stefanfisk commented 9 years ago

I know this is a large and open question for a macro based library like LCL, but are there any thoughts about adding Swift support?

Right now I'm working on a mixed project, and the fact that my logging is a world of pain compared to the wonderful qlog makes me sad 😿

I'd be willing to do some coding if anyone can come up with a nice approach, and and all constructive suggestions would be much appreciated!

aharren commented 9 years ago

No nice ideas from my side yet :(

stefanfisk commented 8 years ago

So I just had an epiphany:

lcl.swift

class lcl {
    private let _component: _lcl_enum_component_t;

    init(_ component: _lcl_enum_component_t) {
        _component = component
    }

    private func log(level: _lcl_enum_level_t, @autoclosure message: () -> String) {
        let activeLevel = _lcl_component_level_ptr[Int(level.rawValue)]

        if level.rawValue < UInt32(activeLevel) {
            return
        }

        _lcl_logger_swift_support(_component.rawValue, level.rawValue, message())
    }

    func critical(@autoclosure message: () -> String = "") {
        log(lcl_vCritical, message: message)
    }
    func error(@autoclosure message: () -> String = "") {
        log(lcl_vError, message: message)
    }
    func warning(@autoclosure message: () -> String = "") {
        log(lcl_vWarning, message: message)
    }
    func info(@autoclosure message: () -> String = "") {
        log(lcl_vInfo, message: message)
    }
    func debug(@autoclosure message: () -> String = "") {
        log(lcl_vDebug, message: message)
    }
    func trace(@autoclosure message: () -> String = "") {
        log(lcl_vTrace, message: message)
    }
}

lcl_swift.h

#import <lcl.h>

extern _lcl_level_narrow_t* _lcl_component_level_ptr;

static inline void _lcl_logger_swift_support(_lcl_component_t component, _lcl_level_t level, const char* message) {
    _lcl_logger(component, level, "%s", message);
}

lcl_swift.h

#import "lcl_swift.h"

_lcl_level_narrow_t* _lcl_component_level_ptr = _lcl_component_level;

Then in the top of you source file do:

private let log = lcl(lcl_cComponent)

And you will be able to log via log.trace("Test") etc.

stefanfisk commented 8 years ago

The c wrangling can probably be cleaned up, but my understanding of Swift<->C interoperability is far from complete.

stefanfisk commented 8 years ago

Aaaand I just realized it is missing file/line/function/etc...

Will do another take tomorrow, and if it all feels good probably create a Pod.

aharren commented 8 years ago

That sounds promising :)

stefanfisk commented 8 years ago

Alright, I've got it working, but I am not sure how to package it as a pod. The issue is that the following code needs to be built with _lcl_logger defined, and preferably with -w to suppress warnings related to redefining builtins. Do you have any idea on how to best achieve that?

#import "lcl_swift.h"

_lcl_level_narrow_t* _lcl_component_level_swift_support = _lcl_component_level;

void _lcl_logger_swift_support(_lcl_component_t component, _lcl_level_t level, const char* message, const char* file, long line, const char* function) {
    #define __FILE__ file
    #define __LINE__ (int)line
    #define __PRETTY_FUNCTION__ function
    #define __func__ function
    #define __FUNCTION__ function

    _lcl_logger(component, level, "%s", message);
}