Yan Pujante
08/07/2019, 6:52 PMpackage sample
import platform.AppKit.NSView
fun attached(parent: NSView) : Boolean {
println("kotlin::attached(${parent.window()})")
return true
}
Then I have another (C++) project consuming the library and calling:
lib->kotlin.root.sample.attached({ parent }))
where parent
is a NSView
that was created by some code I am not responsible for (it is passed to me).
This simple code crashes...
From the screenshot attached I can confirm that what is passed to me is a NSView
pointer... but somehow on the kotlin side it crashes. I have tried with a few methods on NSView
and they all trigger a crash.
Any idea? Am I doing something wrong?Kris Wong
08/07/2019, 7:17 PMYan Pujante
08/07/2019, 8:57 PMKris Wong
08/07/2019, 9:00 PMsvyatoslav.scherbina
08/08/2019, 12:43 PMThis is wrong. You pass a struct with pointer tolib->kotlin.root.sample.attached({ parent }))
NSView
where pointer to Kotlin object was expected.Kris Wong
08/08/2019, 1:14 PMsvyatoslav.scherbina
08/08/2019, 2:13 PMYan Pujante
08/08/2019, 2:30 PMimport platform.AppKit.NSView
fun attached(parent: NSView) : Boolean {
println("kotlin::attached(${parent.window()})")
return true
}
This is the generated header:
typedef void* libVst3Kotlin_KNativePtr;
struct libVst3Kotlin_KType;
typedef struct libVst3Kotlin_KType libVst3Kotlin_KType;
typedef struct {
libVst3Kotlin_KNativePtr pinned;
} libVst3Kotlin_kref_platform_AppKit_NSView;
typedef struct {
/* Service functions. */
void (*DisposeStablePointer)(libVst3Kotlin_KNativePtr ptr);
void (*DisposeString)(const char* string);
libVst3Kotlin_KBoolean (*IsInstance)(libVst3Kotlin_KNativePtr ref, const libVst3Kotlin_KType* type);
/* User functions. */
struct {
struct {
struct {
const char* (*helloFromKotlin)();
libVst3Kotlin_KBoolean (*attached)(libVst3Kotlin_kref_platform_AppKit_NSView parent);
} sample;
} root;
} kotlin;
} libVst3Kotlin_ExportedSymbols;
extern libVst3Kotlin_ExportedSymbols* libVst3Kotlin_symbols(void);
and this is what I have on the C++ side:
void attached(NSView *parent) {
// this is wrong... so what is right?
lib->kotlin.root.sample.attached({ parent }));
}
Thankssvyatoslav.scherbina
08/08/2019, 2:47 PMNSView
from AppKit to C++ code.
So I assume this is not pure C++. Do you use Objective-C++ here?Yan Pujante
08/08/2019, 3:00 PMvoid *
so the true api is
void attached(void *parent) {
}
but I know it is a NSView *
as is proven by the stack trace header. I can also simply rename my .cpp
file into .mm
and write the following code:
#include <Cocoa/Cocoa.h>
void attached(void *parent) {
NSView *ptr = reinterpret_cast<NSView *>(parent);
ptr->window();
}
and this works perfectly. So I do know that parent
is NSView *
svyatoslav.scherbina
08/08/2019, 3:28 PMYan Pujante
08/08/2019, 3:38 PMsvyatoslav.scherbina
08/08/2019, 3:46 PMattached
properly would be much easier if Kotlin code was compiled to Objective-C framework.
But it is still possible to do this when compiling Kotlin to C library:
1. Your Kotlin attached
function should take CPointer<*>
parameter, not NSView
. And C++ part should pass parent
itself to attached
.
2. On Kotlin side this pointer can then be converted to NSView
. You have two options here:
a. (Kinda internal, but concise): interpretObjCPointer<NSView>(ptr.rawValue)
b. Write Objective-C function to convert pointer to Objective-C reference (using (__bridge NSView*)ptr
), and call it from Kotlin using cinterop
. Note that you can include this entire function to your .def
file.Yan Pujante
08/08/2019, 3:52 PMparent
(which is void *
) as provided by the SDK. I will try your suggestion 1. and 2.a (I am not sure I understand 2.b but let me start with "easy" 😉)Yan Pujante
08/08/2019, 4:42 PMfun attached(parent: CPointer<*>) : Boolean {
val view = interpretObjCPointer<NSView>(parent.rawValue)
println("kotlin::attached(tag=${view.tag()}, window=${view.window()})")
return true
}
and the C++ side is (much simpler):
// parent is void *
lib->kotlin.root.sample.attached(parent);
and the output proving it works...
kotlin::attached(tag=-1, window=<SMTGCocoa1507737125_DocumentWindow: 0x7fd387d3ff20>)