cgo on macOS - unknown type name NSString - macos

In a go code i have following code:
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -L./ ${SRCDIR}/test.dylib -framework Foundation
#include "./test.h"
#include <stdlib.h>
#include <stdio.h>
#import <Foundation/Foundation.h>
#import <Foundation/NSString.h>
*/
import "C"
test.h has a struct with NSString
On building the go code it shows
error: unknown type name 'NSString' NSString nspath,
can someone guide what's wrong here since i have included appropriate objective C libraries and headers.

Not running OSX/iOS, but looking at github, it looks like at least some developers wrap objective-c code in the cgo preamble inside a typical C function.
This looks like a particularly good example:
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation
#import <Foundation/NSBundle.h>
#import <Foundation/NSString.h>
#include <stdlib.h>
#include <string.h>
const char *assets_zip_path() {
NSString *path = [[NSBundle mainBundle] pathForResource: #"aaaaxy" ofType: #"dat"];
const char *data = [path UTF8String];
if (data == NULL) {
return NULL;
}
return strdup(data);
}
*/
import "C"
func openAssetsZip() (*os.File, error) {
pathCStr := C.assets_zip_path()
...
You also may already find the bindings you need in the go/mobile package.

Related

Can't GTK3 programs be in multiple source files?

I am trying to make a C-program with multiple c-files in GTK3.
As models I am using:
how-to-split-a-c-program-into-multiple-files
and this
example-0.c
My program looks like this:
Functions.c (with the function activate)
#include "Functions.h"
#include <gtk/gtk.h>
#include "stdio.h"
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
gtk_widget_show_all (window);
}
Function.h (the header file)
#include <gtk/gtk.h>
#ifndef FUNCTIONS_H_INCLUDED
#define FUNCTIONS_H_INCLUDED
static void activate (GtkApplication* app, gpointer user_data);
#endif
Main.c
#include "stdio.h"
#include <gtk/gtk.h>
#include "Functions.h"
int main(int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
When I compile, is says:
gcc -Wall `pkg-config --cflags gtk+-3.0` Functions.c Main.c `pkg-config --libs gtk+-3.0`
Functions.c:7:13: warning: ‘activate’ defined but not used [-Wunused-function]
static void activate (GtkApplication* app, gpointer user_data)
^
In file included from Main.c:4:0:
Functions.h:7:14: warning: ‘activate’ used but never defined
static void activate (GtkApplication* app, gpointer user_data);
^
/tmp/ccWzazr0.o: I funktionen "main":
Main.c:(.text+0x38): undefined reference to `activate'
collect2: error: ld returned 1 exit status
and is not compiled!
Yes, GTK programs can be split into multiple C files.
You get an error because you are telling your compiler that the function is only visible within that single C source file:
static void activate (GtkApplication* app, gpointer user_data)
If you want to use that function from another source file, you need to remove static keyword.
Both in the header file as well in the C file you need to remove it.

Importing C.scintilla_new() in Cgo package

package main
//#cgo CFLAGS: -I/home/me/geany/scintilla/include
//#include <ScintillaWidget.h>
import "C"
import (
"github.com/mattn/go-gtk/gtk"
)
func main() {
gtk.Init(nil)
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)
window.SetPosition(gtk.WIN_POS_CENTER)
window.SetTitle("GTK Go!")
window.SetIconName("textview")
window.Connect("destroy", gtk.MainQuit)
window.SetSizeRequest(600, 600)
C.scintilla_new();
window.ShowAll()
gtk.Main()
}
This is the error I get:
# _/home/me/gosci/gosci
could not determine kind of name for C.scintilla_new
The definition is obviously in the header at line 58:
GtkWidget* scintilla_new (void);
How to compile this?
Possibly GtkWidget is not declared in ScintillaWidget.h and you need to #include <gtk/gtk.h> first.

Gulp-sass not compiling Foundation 6 properly

I'm having some issues with Foundation 6 files, for some reasons they are just not including all of the sass components. I tried to use Foundation 5 and it worked fine.
Here is my gulp task:
gulp.task('styles', ['clearCss'], function() {
gulp.src('assets/sass/app.scss')
.pipe(plumber(plumberErrorHandler))
.pipe(sourcemaps.init())
.pipe(sass({
outputStyle: 'compressed'
})
.on('error', notify.onError(function(error) {
return "Error: " + error.message;
}))
)
.pipe(autoprefixer({
browsers: ['last 2 versions', 'ie >= 9']
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./assets/dist/css'))
.pipe(browserSync.stream({match: '**/*.css'}))
.pipe(notify({
message: "Styles task complete!"
}));
});
And here is my app.scss:
// Import Foundation
#import "../components/foundation/scss/foundation";
It works with my own sass files, but completely ignoring foundation parts.
You should import a file foundation-sites.scss, not scss/foundation.scss. File foundation.scss has only a #mixin foundation-everything which is included in foundation-sites.scss:
#include foundation-everything;
However foundation-sites.scss has an error in 6.0.4, this is my log:
Error in plugin 'sass'
Message:
bower_components\foundation-sites\foundation-sites.scss
Error: File to import not found or unreadable: foundation
Parent style sheet: stdin
on line 1 of stdin
>> #import 'foundation';
The fix:
Change line nr 1 in file foundation-sites.scss from
#import 'foundation'; to #import 'scss/foundation';
The Correct Approach for foundation 6 :
if you Look at the foundation.scss file (https://github.com/zurb/foundation-sites-6/blob/develop/scss/foundation.scss)
Yes it imports all the required components, but since they are now mixins and not regular sass you have to explictly tell that you want to make use of them, by simply calling the mixin.
app.scss
#import 'foundation';
#include foundation-everything; // Very important if you want to include all of foundation css to your complied css
gulpfile.js
gulp.task('scss', function() {
return gulp.src('app.scss')
.pipe(plugins.sass(
{includePaths: ['./node_modules/foundation-sites/scss']}
))
.pipe(gulp.dest('css'))
.pipe(plugins.notify({ message: 'Sass task complete' }));
});
I have gulp-sass working with foundation-sites (Foundation 6):
My main.scss file:
#charset 'UTF-8';
/**
* Main SCSS
* Version 1.0.0
* built with foundation-sites
*/
// import custom settings
#import 'settings';
// import foundation sass
#import "../bower_components/foundation-sites/scss/foundation";
/* either include all foundation components… //*/
#include foundation-everything;
/* or include specific foundation components //*/
// #include foundation-global-styles;
/* include either foundation-grid… //*/
// #include foundation-grid;
/* or foundation-flex-grid (but don't include both) //*/
// #include foundation-flex-grid;
// #include foundation-typography;
// #include foundation-button;
// #include foundation-forms;
// #include foundation-visibility-classes;
// #include foundation-float-classes;
// #include foundation-accordion;
// #include foundation-accordion-menu;
// #include foundation-badge;
// #include foundation-breadcrumbs;
// #include foundation-button-group;
// #include foundation-callout;
// #include foundation-close-button;
// #include foundation-drilldown-menu;
// #include foundation-dropdown;
// #include foundation-dropdown-menu;
// #include foundation-flex-video;
// #include foundation-label;
// #include foundation-media-object;
// #include foundation-menu;
// #include foundation-off-canvas;
// #include foundation-orbit;
// #include foundation-pagination;
// #include foundation-progress-bar;
// #include foundation-slider;
// #include foundation-sticky;
// #include foundation-reveal;
// #include foundation-switch;
// #include foundation-table;
// #include foundation-tabs;
// #include foundation-thumbnail;
// #include foundation-title-bar;
// #include foundation-tooltip;
// #include foundation-top-bar;
If you don't want to load all the foundation componenents, you don't have to. Instead of #include foundation-everything, simply #include the specific components you need.
What I did with my gulp + bower setup:
/src/scss/app.scss
#import 'settings';
#import '../../bower_components/foundation-sites/scss/foundation';
#include foundation-everything;
settings.scss contained my foundation variable overrides, custom CSS, etc. Trick for me was to #import full file path then #include the mixin.
Though it is excessive to include everything, I prefer to develop with no hassles then use uncss to clean out dead CSS code.
I had to edit the foundation-sites' bower.json file to change the main.scss foundation #import.
From:
"main": [
"scss/foundation.scss",
"js/foundation.js"
],
To:
"main": [
"foundation-sites.scss",
"js/foundation.js"
],
As well as the foundation-sites.scss file.
#import 'foundation';
To:
#import 'scss/foundation.scss';
I don't think this is the best route to take but my sass, grunt and bower knowledge is limited.
If you have a gulpfile, include 'node_modules/foundation-sites/scss' and then in your app.scss or style.scss do the following:
#import "settings/settings";
#import "foundation";
#include foundation-everything;
That way you'll import EVERYTHING Foundation has to offer. Of course, everything might be a tad overkill, but that's an optional choice.
Example of gulp task:
gulp.task('css', function() {
return gulp.src(assets + 'scss/*.scss')
.pipe(sass({
includePaths: 'node_modules/foundation-sites/scss',
errLogToConsole: true
}))
.on('error', handleError)
.pipe(prefixer())
.pipe(gulp.dest(themeDir))
.pipe(browserSync.stream());
});
Of course, handleError needs to be defined. In my case, it's defined as:
var handleError = function(err) {
if (err) {
var args = Array.prototype.slice.call(arguments);
console.log(args);
this.emit('end');
}
};
Don't forget to include the required dependencies.

CGO undefined reference in included files

Wraping up OpenJtalk in Go, files are successfully included and types are referenced without an issue, but functions trigger an undefined reference error.
jtalk.go:
package main
// #cgo CFLAGS: -I/home/vagrant/open_jtalk/njd [...etc]
/*
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <math.h>
// Main headers
#include "mecab.h"
#include "njd.h"
#include "jpcommon.h"
#include "HTS_engine.h"
// Sub headers
#include "text2mecab.h"
#include "mecab2njd.h"
#include "njd_set_pronunciation.h"
#include "njd_set_digit.h"
#include "njd_set_accent_phrase.h"
#include "njd_set_accent_type.h"
#include "njd_set_unvoiced_vowel.h"
#include "njd_set_long_vowel.h"
#include "njd2jpcommon.h"
*/
import "C"
type Open_JTalk struct {
mecab C.Mecab each of these struct references are fine
njd C.NJD
jpcommon C.JPCommon
engine C.HTS_Engine
}
func (open_jtalk *Open_JTalk) Open_JTalk_initialize() {
C.Mecab_initialize(&open_jtalk.mecab) // when any function is called the error happens
C.NJD_initialize(&open_jtalk.njd)
C.JPCommon_initialize(&open_jtalk.jpcommon)
C.HTS_Engine_initialize(&open_jtalk.engine)
}
func main() {
}
And the weird part is that those same functions are declared right after the types:
mecab.h
// line 1584
typedef struct _Mecab{
char **feature;
int size;
mecab_t *mecab;
} Mecab;
BOOL Mecab_initialize(Mecab *m);
Project webpage: http://open-jtalk.sourceforge.net/
You need to add cgo linker options (LDFLAGS) with the path to and the name of your library. e.g.
// #cgo CFLAGS: -Iyour-include-path
// #cgo LDFLAGS: -Lyour-library-path -lyour-library-name-minus-the-lib-part

What is the exact equivalent to LD_PRELOAD on OSX?

I am using LD_PRELOAD to hook a library function, and in Linux it works perfectly. But I cannot figure out how to do the equivalent in OSX.
The setup I have on Linux is as follows:
The code is:
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <unistd.h>
#include <ruby.h>
void
rb_raise(unsigned long exc, const char *fmt, ...)
{
static void (*libruby_rb_raise)
(unsigned long exc, const char *fmt, ...) = NULL;
void * handle;
char * error;
if (!libruby_rb_raise) {
handle = dlopen("/path/to/libruby.so",
RTLD_LAZY);
if (!handle) {
fputs(dlerror(), stderr);
exit(1);
}
libruby_rb_raise = dlsym(handle, "rb_raise");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
}
// ...code...
return Qnil;
}
Which I then compile with:
gcc -Wall -O2 -fpic -shared -ldl -g -I/path/to/includes/ -o raise_shim.so raise_shim.c
I then execute with:
LD_PRELOAD=./raise_shim.so ruby
All of the above works well on Linux, what is the equivalent for each step to get this working on OSX? I have googled this and have not been able to get it to work with the information provided as the info for some of the steps are missing.
Thanks in advance!
Take a look at DYLD_INSERT_LIBRARIES. That's the variable you're looking for.
See also this answer.

Resources