don't pass go strings to c - pass char*+len, callee must call free()

This commit is contained in:
mappu 2017-05-20 23:02:58 +12:00
parent b6d1cafe54
commit d32ab82d73
3 changed files with 45 additions and 24 deletions

35
main.go
View File

@ -31,24 +31,27 @@ func Bolt_Options_New_Readonly() ObjectReference {
}
//export Bolt_Open
func Bolt_Open(path string, mode uint32, opts ObjectReference) (ObjectReference, string) {
func Bolt_Open(path string, mode uint32, opts ObjectReference) (ObjectReference, *C.char, int) {
optsIFC, ok := gms.Get(opts)
if !ok {
return 0, ""
errMsg := NullObjectReference.Error()
return 0, C.CString(errMsg), len(errMsg)
}
ptrBoltOps, ok := optsIFC.(*bolt.Options)
if !ok {
return 0, ""
errMsg := NullObjectReference.Error()
return 0, C.CString(errMsg), len(errMsg)
}
ptrDB, err := bolt.Open(path, os.FileMode(mode), ptrBoltOps)
if err != nil {
return 0, err.Error()
errMsg := err.Error()
return 0, C.CString(errMsg), len(errMsg)
}
dbRef := gms.Put(ptrDB)
return dbRef, ""
return dbRef, nil, 0
}
func withBoltDBReference(b ObjectReference, fn func(db *bolt.DB) error) error {
@ -134,28 +137,31 @@ const (
)
//export GetNext
func GetNext(oRef ObjectReference) (int64, string) {
func GetNext(oRef ObjectReference) (int64, *C.char, int) {
pNC_Iface, ok := gms.Get(oRef)
if !ok {
return ERROR_AND_STOP_CALLING, NullObjectReference.Error()
msg := NullObjectReference.Error()
return ERROR_AND_STOP_CALLING, C.CString(msg), len(msg)
}
pNC, ok := pNC_Iface.(*NextCall)
if !ok {
return ERROR_AND_STOP_CALLING, NullObjectReference.Error()
msg := NullObjectReference.Error()
return ERROR_AND_STOP_CALLING, C.CString(msg), len(msg)
}
cr, ok := <-pNC.content
if !ok {
gms.Delete(oRef)
return FINISHED_OK, ""
return FINISHED_OK, nil, 0
}
if cr.e != nil {
return ERROR_AND_KEEP_CALLING, cr.e.Error()
msg := cr.e.Error()
return ERROR_AND_KEEP_CALLING, C.CString(msg), len(msg)
}
return REAL_MESSAGE, cr.s
return REAL_MESSAGE, C.CString(cr.s), len(cr.s)
}
//export Bolt_ListBucketsAtRoot
@ -164,17 +170,18 @@ func Bolt_ListBucketsAtRoot(b ObjectReference) ObjectReference {
}
//export Bolt_Close
func Bolt_Close(b ObjectReference) string {
func Bolt_Close(b ObjectReference) (*C.char, int) {
err := withBoltDBReference(b, func(db *bolt.DB) error {
return db.Close()
})
if err != nil {
return err.Error()
msg := err.Error()
return C.CString(msg), len(msg)
}
gms.Delete(b)
return ""
return nil, 0
}
func main() {

14
qbolt.h
View File

@ -61,7 +61,8 @@ extern GoInt64 Bolt_Options_New_Readonly();
/* Return type for Bolt_Open */
struct Bolt_Open_return {
GoInt64 r0;
GoString r1;
char* r1;
GoInt r2;
};
extern struct Bolt_Open_return Bolt_Open(GoString p0, GoUint32 p1, GoInt64 p2);
@ -71,14 +72,21 @@ extern GoInt64 Bolt_ListBuckets(GoInt64 p0, GoSlice p1);
/* Return type for GetNext */
struct GetNext_return {
GoInt64 r0;
GoString r1;
char* r1;
GoInt r2;
};
extern struct GetNext_return GetNext(GoInt64 p0);
extern GoInt64 Bolt_ListBucketsAtRoot(GoInt64 p0);
extern GoString Bolt_Close(GoInt64 p0);
/* Return type for Bolt_Close */
struct Bolt_Close_return {
char* r0;
GoInt r1;
};
extern struct Bolt_Close_return Bolt_Close(GoInt64 p0);
#ifdef __cplusplus
}

View File

@ -13,8 +13,9 @@ BoltDB* BoltDB::createFrom(QString filePath, QString &errorOut)
GoString filePathGS = Interop::toGoString_WeakRef(&filePathBytes);
auto open_ret = ::Bolt_Open(filePathGS, 0444, opts);
if (open_ret.r1.n != 0) {
errorOut = QString(open_ret.r1.p);
if (open_ret.r2 != 0) {
errorOut = QString::fromUtf8(open_ret.r1, open_ret.r2);
free(open_ret.r1);
return nullptr;
}
@ -38,11 +39,13 @@ bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb)
auto gnr = ::GetNext(listJob);
if (gnr.r0 == ERROR_AND_STOP_CALLING) {
errorOut.append(QString(gnr.r1.p)); // log error
errorOut.append(QString::fromUtf8(gnr.r1, gnr.r2)); // log error
free(gnr.r1);
break; // done
} else if (gnr.r0 == ERROR_AND_KEEP_CALLING) {
errorOut.append(QString(gnr.r1.p)); // log error
errorOut.append(QString::fromUtf8(gnr.r1, gnr.r2)); // log error
free(gnr.r1);
continue;
} else if (gnr.r0 == FINISHED_OK) {
@ -50,7 +53,8 @@ bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb)
break;
} else if (gnr.r0 == REAL_MESSAGE) {
cb(QByteArray(gnr.r1.p, gnr.r1.n));
cb(QByteArray(gnr.r1, gnr.r2));
free(gnr.r1);
continue;
}
}
@ -60,9 +64,11 @@ bool BoltDB::listBucketsAtRoot(QString& errorOut, NameReciever cb)
BoltDB::~BoltDB()
{
GoString err = ::Bolt_Close(this->gmsDbRef);
if (err.n != 0) {
auto err = ::Bolt_Close(this->gmsDbRef);
if (err.r1 != 0) {
// Error closing database!
// Need to display an alert... somewhere
free(err.r0);
}
}