I have a drawing program that uses SDL, written in C++. I would like to create a graphical interface only in Vala and use it to call functions from a program (functions are ready to use and I only want to call them from the GUI). I was looking for solutions as VAPI, and I was thinking of using GObject, but I can not embrace both. Has anyone done similar things and can you suggest me a solution to my problem?
If you want to use the C++ code in Vala we prepare them properly. Here's an example.
First you have to tell the valac compiler that the function is defined somewhere else. Let's use the extern directive.
// ccodetest.vala
extern void cpp_test_function ();
void main () {
stdout.printf ("This is Vala code\n");
cpp_test_function ();
}
Then the functions in C++ are properly linked with the object files derived from C, we declare them as extern "C".
// cpplibrary.cpp
# include
using namespace std;
extern "C" void cpp_test_function () {
cout << "This is a C + + code\n";
}
When we are so ready, we can compile Vala code to C. We get ccodetest.c.
valac -C ccodetest.vala
Now we can use gcc to compile the object file. We get ccodetest.o.
gcc-o ccodetest.o ccodetest.c-c-I /usr/include/glib-2.0/ -I /usr/include/glib-2.0/glib/ -I /usr/lib/glib-2.0/include/
File C++ compile as follows.
g++ -o cpplibrary.cpp.o cpplibrary.cpp -c
At the end we linking both files.
g++ -o ccode_test ccodetest.o cpplibrary.cpp.o -L /usr/lib/ -lglib-2.0 -lgobject-2.0
The program works as follows:
$ ./ccode_test
This is Vala code
This is a C++ code
Related
I'm trying to compile a simple empty module example (using gcc 11.2):
// my_module.cc:
export my_module;
// main.cc:
import my_module;
int main() { return 0; }
Using these compilation commands:
g++ my_module.cc -std=c++20 -fmodules-ts -c
g++ main.cc -std=c++20 -fmodules-ts my_module.o
This compiles fine.
However, even though the module is empty, I need the module's object file (my_module.o) when compiling main.cc, because the linker wants the function _ZGIW9my_moduleEv. I'm assuming this function is meant to perform initialization for static variables or something similar, as it will call __static_initialization_and_destruction_0 if I define static variables in the module.
My question is, does every module really need an object file? Is there any way to mark a named module as "doesn't need initialization, all my functions are inline"?
I think that header units could be used like this, but they're supposedly meant only as a transitory solution and have other downsides like macro hygiene.
I have a file build and compiled correctly in ADA (a simple Hello world). I want to execute the file .o from a c++ using taskspawn. To do that I have read that you must declare in the c++ something like that:
...
#include <taskLib.h>
/* Ada binder-generated main - ADA_MAIN is passed as a macro from the makefile */
extern void ADA_MAIN(void);
void UsrAppInit()
{
int stackSize = 0x80000;
int spawnFlags = VX_FP_TASK;
/* MAIN_TASK_NAME is passed as a macro from the makefile */
char * mainTaskName = (char *) MAIN_TASK_NAME;
int priority = 100;
/* Spawn Ada environment task */
taskSpawn(mainTaskName, priority, spawnFlags, stackSize,
(FUNCPTR) ADA_MAIN, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}
to complete the process I have declared the ADA_MAIN as a MACRO in makefile (in my case the makefile is makefile.mk)
(MAIN_ADA pathOfmyADAexe and MAIN_TASK_NAME "the procedure of the helloworld")
but the MACRO are not recognized in the process so I have error in compilation for MAIN_TASK_NAME and ADA_MAIN. Any suggestion about how am I missing? I could also do in different way but how?
I don’t know about your ADA_MAIN, and you don't tell us what your MACRO is, so it's a little hard to talk about them. Also, it's a while since I used VxWorks (and, then, we were supported, so had access to a cross-compiler that did the build for us: and our main program was in Ada).
That said, your problem comes down to building a program with Ada components where the main program isn't in Ada.
Ada programs need elaboration. This is the process that calls in all the components of the runtime library and arranges for them to be initialized in the right order. What components, you ask? well, for instance, there's the obvious Ada.Text_IO; and there's the less-obvious things, such as exception handling.
The elaboration code is generated using gnatbind.
Given this hello.adb
with Ada.Text_IO;
procedure Hello is
begin
Ada.Text_IO.Put_Line ("hello!");
end Hello;
you really need to supply a specification, as otherwise the compiler will generate a linker name such as __ada_hello; take control by hello.ads,
procedure Hello with
Export,
Convention => C,
External_Name => "hello";
You'll be using a cross-compilation suite. The components are prefixed by the target name, e.g. powerpc-wrs-vxworks-gnatmake, arm-eabi-gnatbind, but I'll just use the bare component name below.
$ gnatmake -c hello.adb
which generates hello.o, hello.ali (if the program was more complicated, it'd compile the closure too).
Now bind:
$ gnatbind -n -Lhello -static hello.ali
where
-n : main program not in Ada
-Lhello: adainit, adafinal renamed helloinit, hellofinal
-static: pretty sure VxWorks doesn't support shared libraries?
generating b~hello.ads, b~hello.adb (depending on the compiler release, the ~ may be replaced by e.g. double underscore). Compile:
$ gnatmake -c b~hello.adb
Now, to call from C++. you need to tell the compiler about the symbols in the Ada code, in e.g. hello.h:
extern "C" {
void helloinit();
void hellofinal();
void hello();
}
and then the main program in main.cc:
#include "hello.h"
int main() {
helloinit();
hello();
hellofinal();
}
which leaves you with the C++ compile and link, which needs the Ada runtime in libgnat.a and (for tasking) libgnarl.a, and is of course very compiler- and installation-specific: here, on the macOS host, I used
$ g++ main.cc b~hello.o hello.o /opt/gcc-8.1.0/lib/gcc/x86_64-apple-darwin15/8.1.0/adalib/libgnat.a
$ ./a.out
hello!
Translating this to the VxWorks context, I'd say that you'd call helloinit() from your main program (you probably won't need hellofinal()), and pass hello to taskSpawn() in place of your ADA_MAIN.
I'm trying to compile a simple HelloWorld Prgramm from C++ to Javascript using emscripten.
It works fine when I include a main function which call's e.g. the multi function.
Here is my code (HelloWorld.cpp).
#include <stdio.h>
class HelloWorld {
public: void sayHello() {
printf("Hello World Klasse! %f", multi(7));
}
public: double multi(double x){
return x * x;
}
};
However if I don't include a main function the emcc compile always put's out
ERROR root: No functions to process. Make sure you prevented LLVM
from eliminating them as dead (use EXPORTED_FUNCTIONS if necessary,
see the FAQ)
I know about the 'EXPORTED_FUNCTIONS' option which tells what functions should be included into the compile .js file.
I tried various diffrent things:
Using the mangling name, as far as I understood this the name should be '_multi_d10HelloWorldd'. I also tried without classname and some other combinations.
emcc -s HelloWorld.cpp -s EXPORTED_FUNCTIONS='["_multi_d10HelloWorldd"]'
Using the modifier EXPORT_ALL
emcc -s HelloWorld.cpp -s EXPORT_ALL=1
Whatever I do the functions won't be included in the final js file.
From what I understand from the EMCC FAQ I need to use EXPORTED_FUNCTIONS so I can later on call the desired function e.g. 'sayHello' from JS unsing the same method name.
And this is exactly what I need to do later on.
Could someone please point me to a solution or any other possible option which I may have not thought of ?
Is the mangling name I thought of correct ?
Create an "extern c" block. Inside this block define the functions you want to expose to javascript. These functions should be prefixed with an underscore. Inside one of these functions you can instantiate your C++ class.
This is the same approach as one would take when writing a dynamic library, which has the advantage that you can reuse your library in a native program should you wish.
I have a project where I would like to load Go plugins inside a C++ application.
After a lot of research, it is not clear for me whether or not Go supports this.
I encountered a lot of discussions pointing out the bad habit of dynamic linking, proning IPC instead. Moreover it is not clear for me if dynamic linking is intended by the language or not (new Go philosophy ?).
cgo provides the ability to call C from Go or Go from C (inside Go), but not from plain old C. Or does it ?
gc doesn't seem to support shared library (even if https://code.google.com/p/go/issues/detail?id=256 mentions it does)
gccgo support Go shared libraries but I couldn't make it work (probably because the main entry point is not in Go ...)
SWIG doesn't seem to help either :(
Apparently something is going on upstream as well (https://codereview.appspot.com/7304104/)
main.c
extern void Print(void) __asm__ ("example.main.Print");
int main() {
Print();
}
print.go
package main
import "fmt"
func Print() {
fmt.Printf("hello, world\n")
}
Makefile :
all: print.o main.c
gcc main.c -L. -lprint -o main
print.o: print.go
gccgo -fno-split-stack -fgo-prefix=example -fPIC -c print.go -o print.o
gccgo -shared print.o -o libprint.so
Output :
/usr/lib/libgo.so.3: undefined reference to `main.main'
/usr/lib/libgo.so.3: undefined reference to `__go_init_main'
Is there a solution for that ? What is the best approach ? forking + IPC ?
References :
cgo - go wiki
callback in cgo
c callbacks and non go threads
cgo - golang
call go function from c
link c code with go code
I don't think you can embed Go into C. However you can embed C into Go and with a little stub C program you can call into C first thing which is the next best thing! Cgo definitely supports linking with shared libraries so maybe this approach will work for you.
Like this
main.go
// Stub go program to call cmain() in C
package main
// extern int cmain(void);
import "C"
func main() {
C.cmain()
}
main.c
#include <stdio.h>
// Defined in Go
extern void Print(void);
// C Main program
int cmain() {
printf("Hello from C\n");
Print();
}
print.go
package main
import "fmt"
import "C"
//export Print
func Print() {
fmt.Printf("Hello from Go\n")
}
Compile with go build, and produces this output when you run it
Hello from C
Hello from Go
AFAIK, you cannot compile a Go package to a shared library witg 'gc' ATM, it may change in the future. There might be some chance with 'gccgo' as 'libgo' (Go runtime, I suppose) is a shared library already. I guess the missing piece is then only to properly initialize the runtime, which normally a Go command handles automatically.
The gccgo expert is I.L. Taylor, he is reachable at the golang-nuts mailing list almost daily. I suggest to ask him directly.
PS: Other problems possibly include the interaction of the Go garbage collector and the (C++) process memory etc. Maybe I'm too optimistic and it is not at all feasible.
I am trying to create a program that is completely hosted in Eclipse, starts in C++, and calls Ada. I have GNATBench loaded, and can run Ada programs without a problem. What I cannot do is have a C++ project call an Ada project.
After hunting around, I found and executed the code shown below using a make file.
http://www.pegasoft.ca/resources/boblap/book.html
I also found a post stating that my goal has been done.
http://blogs.windriver.com/parkinson/2009/10/yesterday-adacore-announced-the-release-of-gnatbench-231-its-ada-integrated-development-environment-eclipse-plugin-which.html
What else do I need to include to have C++ in Eclipse call Ada in Eclipse?
USING MAKE FILE:
$ c++ -c test.cc
$ gnatgcc -c test_subr
$ gnatbind -n test_subr
$ gnatgcc -c b~test_subr
$ gnatlink -o main test.o test_subr.ali --link=c++
$ ./main
CPP Code:
//main.cc
#include extern "C" void adainit(void);
#include extern "C" void adafinal(void);
#include extern "C" void ada_subroutine(void);
int main(int argc, char **argv)
{
puts("C++ main");
adainit();
ada_subroutine();
adafinal();
puts("C++ done");
return 0;
}
Ada Code:
package Test_Subr is
procedure Ada_Subroutine;
pragma export(CPP, Ada_Subroutine);
end Test_Subr;
with Ada.Text_IO;
use Ada.Text_IO;
package body Test_Subr is
procedure Ada_Subroutine is
begin
put("IN ADA");
end Ada_Subroutine;
end Test_Subr;
Have you tried using the External_Name parameter of the Export pragma? (IIRC, C++ linkages can get quite mangled.)
pragma Export
( Convention => CPP,
Entity => Ada_Subroutine,
External_Name => "Ada_Subroutine "
);
I don’t know Eclipse; but, how would you get a C++ project in Eclipse to call up another C++ project? or one written in C?
You might be able to get Eclipse to build the Ada as a library and invoke that from the C++?
In the general case, you need to use extern C on the C++ side and pragma exprort (C, .. on the Ada side to get both linkages (parameter passing schemes) the same. However, if you are using gcc for both Ada and C++ then you could use pragma export (CPP instead.
There is one more nit you have to be aware of. If your "main" (the program's entry point) is not written in Ada, then you will need to manually invoke Ada's elaboration process (via the routine adainit()) once before calling anything. Likewise you should in most cases call adafinal() before exiting your program.