Skip to content

Commit

Permalink
Making box classes names unique for each shared lib
Browse files Browse the repository at this point in the history
  • Loading branch information
gershnik committed Jan 10, 2024
1 parent 62ce159 commit f1930ba
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
### Changed
- `BlockUtil.h`: `makeBlock` is deprecated in ObjectiveC++. Modern versions of Clang allow conversions from lambdas to block directly doing essentially what `makeBlock` was doing. Note that it is still available and necessary in C++.
- `BoxUtil.h`: boxing now detects comparability and enables `compare:` not just via presence of operator `<=>` but also when only operators `<`, `==`, `<=` etc. are present.
- `BoxUtil.h`: generated ObjectiveC box classes now have names unique to each shared library/main executable, preventing collisions if multiple modules use boxing.

## [2.3] - 2024-01-09

Expand Down
30 changes: 20 additions & 10 deletions include/objc-helpers/BoxUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
#include <objc/runtime.h>
#import <Foundation/Foundation.h>

#include <dlfcn.h>

#include <cxxabi.h>

#include <concepts>
#include <string>
#include <ostream>
#include <sstream>
#include <filesystem>


/**
Expand All @@ -39,7 +42,7 @@



namespace BoxMakerDetail {
namespace BoxMakerDetail __attribute__((visibility("hidden"))) {
using std::to_string;


Expand Down Expand Up @@ -71,14 +74,21 @@ namespace BoxMakerDetail {
SEL compareSel = @selector(compare:);

Class NSObjectClass = NSObject.class;
id (*NSOBject_initIMP)(id, SEL);
id (*NSObject_initIMP)(id, SEL);
std::string modulePrefix;

ObjcData():
NSOBject_initIMP((decltype(NSOBject_initIMP))class_getMethodImplementation(NSObjectClass, initSel))
{}
ObjcData(const void * sym):
NSObject_initIMP((decltype(NSObject_initIMP))class_getMethodImplementation(NSObjectClass, initSel)) {

Dl_info info;
if (!dladdr(sym, &info))
@throw [NSException exceptionWithName:NSGenericException reason:@"dladdr failed" userInfo:nullptr];
std::filesystem::path mypath(info.dli_fname);
modulePrefix = mypath.stem().string() + '!';
}
};

static const ObjcData data;
static const ObjcData data(&data);
return static_cast<const ObjcData &>(data);
};

Expand Down Expand Up @@ -108,7 +118,7 @@ namespace BoxMakerDetail {


template<class T>
class BoxMaker {
class __attribute__((visibility("hidden"))) BoxMaker {
private:
static auto detectBoxedType() {
if constexpr (std::totally_ordered<T>) {
Expand All @@ -131,7 +141,7 @@ class BoxMaker {

private:

static auto getClassData() -> const BoxMakerDetail::ClassData & {
static __attribute__((visibility("hidden"))) auto getClassData() -> const BoxMakerDetail::ClassData & {

static BoxMakerDetail::ClassData data = [] {
using namespace std::literals;
Expand All @@ -143,7 +153,7 @@ class BoxMaker {
auto & tid = typeid(T);
classData.tName = demangle(tid.name());

std::string className = "BoxerOf_"s + tid.name();
std::string className = objcData.modulePrefix + "Boxed["s + tid.name() + ']';
Class cls = objc_allocateClassPair(objcData.NSObjectClass, className.c_str(), 0);
classData.cls = cls;

Expand Down Expand Up @@ -285,7 +295,7 @@ class BoxMaker {
auto & classData = getClassData();

id obj = class_createInstance(classData.cls, 0);
obj = objcData.NSOBject_initIMP(obj, objcData.initSel);
obj = objcData.NSObject_initIMP(obj, objcData.initSel);
if (!obj)
return nullptr;
auto * dest = classData.addrOfValue(obj);
Expand Down

0 comments on commit f1930ba

Please sign in to comment.