Crystal C binding, simple hello world example. - crystal-lang

I’m trying to figure out how c bindings in crystal work. For starters I’m wondering how I would include a simple hello world c function into crystal. Always good to start with the basics right? Here’s the function I’d like to include:
#include <stdio.h>
void hello(const char * name){
printf("Hello %s!\n", name);
}

That took me a bit to figure out as well. First you'll have to compile your C file into an object. In gcc you would run gcc -c hello.c -o hello.o.
Then in the crystal file you'll need to link to the C object. Here's an example:
#hello.cr
#[Link(ldflags: "#{__DIR__}/hello.o")]
lib Say
fun hello(name : LibC::Char*) : Void
end
Say.hello("your name")
Now you simply have to compile your crystal app and it will work.
crystal build hello.cr

Related

BCC LD86 file has bad magic number

I wanted to write a simple hello world program in DOSBox, so I downloaded Bruce's C Compiler from here. And wrote this program:
#include <stdio.h>
int main() {
printf("Hello, World!\n");
}
I ran bcc like this: bcc -o hello hello.c, but I get this error every time:
C:\BCC\DEVEL\BCC\BIN\LD86.EXE: HELLO.C has bad magic number
I don't know why this is happening, if anyone can tell me please do.

"undefined reference to `WinMain#16'" Error in gcc editor

I am just learning c++ and began to watch a youtube tutorial by thenewboston. Unfortunately he is using Code::Blocks while I am using gcc and I do not have the option to create new class files with a button click and so had to manually create them.
I dont understand why the same code in Code::Blocks and gcc will work in Code::Blocks but not gcc. Does gcc require different coding for the same language?
EDIT: I have downloaded and tested in Code::Blocks myself
Other questions talk of how I need to give windows an entry point, but I dont know how to do that.
Test.cpp Code:
#include <iostream>
#include "ClassTest.h"
using namespace std;
int main() {
ClassTest bo;
}
ClassTest.h Code:
#ifndef CLASSTEST_H
#define CLASSTEST_H
class ClassTest {
public:
ClassTest();
};
#endif // CLASSTEST_H
ClassTest.cpp Code:
#include <iostream>
#include "ClassTest.h"
using namespace std;
ClassTest::ClassTest() {
cout << "blah blah" << endl;
}
I'm not quite sure I understand what the question is; I'm going to take it as "how do I get these three files to build into a .exe that I can run from the Windows commmand line?"
The answer is to run something like this on the command line, in the folder with the files:
g++ -c Test.cpp -o Test.o
g++ -c ClassTest.cpp -o ClassTest.o
g++ Test.o ClassTest.o -o Test.exe
The first two commands build each CPP file into an "object file", which isn't a whole program by itself but which contains the compiled version of the code in that CPP file. The last command tells the compiler to paste together the two object files into a program, and resolve all the cross-references between them. (For example, the part where Test.cpp constructs a ClassTest object needs to end up calling the ClassTest constructor code from ClassTest.cpp.)
Code::Blocks is an IDE and works out how to build each source file in your project and link them together by itself. But if you aren't using an IDE, you need to do that in another way. You can either do it manually like this, or you can write a Makefile that will check which code files have changed and rebuild and re-link everything that depends on them when you run the make command, which is how most people do it.
As for "giving Windows an entry point", that probably refers to GUI applications that want to display windows on the screen. For console programs like the one you have written, the "entry point" is main(), and you just print stuff to the command line window. To make actual Windows-style GUI windows of your own, you need to use the Windows API, which I can't tell you much about.

typeid of enum changing when dynamically linked in matlab mex file

I have a C++ library with a particular function that returns a boost::any, whose value type is a particular enum defined in a different included library. This normally works fine.
But when I link to my library dynamically from a Matlab mex file, typeid(the_enum_t) seems to be different for the things made in my library and those made in the caller, in that it doesn't compare ==. Since I'm actually using flann, whose version of boost::any performs a check based on type_info::==, this makes everything break. Static linking works fine, but that's kind of a pain here, and I'd really rather have it work either way.
I thought type_info::== was supposed to work consistently across library boundaries. Does this have to do with how Matlab dynamically loads libraries from mex?
Here's some code to reproduce this (also available in easy-to-download form, with a makefile, in this gist).
First, a stand-in for the library that defines the enum (flann):
namespace library {
enum the_enum_t { el_one, el_two, el_three };
}
Now a proxy for my library, stubby.hpp:
#include <boost/any.hpp>
#include "the_enum.hpp"
boost::any the_function();
And its implementation stubby.cpp:
#include "stubby.hpp"
boost::any the_function() {
return boost::any(library::el_two);
}
Finally, test code test.cpp, which is compiled with -DNO_MEX for a standalone and not for a mex file:
#include "stubby.hpp"
#include <boost/any.hpp>
#ifdef NO_MEX
#include <cstdio>
using std::printf;
int main() {
#else
#include "mex.h"
void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prsh) {
#endif
boost::any val_any = the_function();
printf("%s (equal: %d)\n",
val_any.type().name(),
val_any.type() == typeid(library::the_enum_t));
}
I get the expected output
N5flann17flann_algorithm_tE (equal: 1)
from each of
$ g++ -o test{,.cpp} -DNO_MEX libstubby.a && ./test
$ g++ -o test{_s,.cpp} -DNO_MEX libstubby.so && ./test_s
$ ln -sf test{,_s}.cpp && mex test_s.cpp libstubby.a && matlab -r test
But dynamically linking a mex file doesn't work:
$ mex test.cpp libstubby.so && matlab -r test
N5flann17flann_algorithm_tE (equal: 0)
I see this same behavior on
Matlab R2011b and R2011a, OSX 10.7, Apple gcc 4.2.1
Matlab R2011b, CentOS 5.7, gcc 4.1.2
Matlab R2010a, Ubuntu 11.04, gcc 4.4.5
The weird thing is that I could've sworn it worked a few months ago, but maybe I just did a bad job of testing.
Obviously I can get around this by static linking. But why is this happening? Does it have something to do with the way Matlab loads mex files and their libraries?
Boost has a workaround for this issue; see https://svn.boost.org/trac/boost/ticket/754
It's possible that boost is failing to enable the workaround. Try passing compiler flag -DBOOST_AUX_ANY_TYPE_ID_NAME per the patch on that ticket.

Python importing & using cdll (with a linux .so file)

After one of my last questions about python&c++ integration i was told to use dlls at windows.
(Previous question)
That worked ok doing:
cl /LD A.cpp B.cpp C.pp
in windows enviroment, after setting the include path for boost, cryptopp sources and cryptopp libraries.
Now i'm tryting to do the same in linux, creating a .so file to import through ctypes on python2.5.
I did:
gcc -Wall -Wextra -pedantic A.cpp B.cpp C.cpp /usr/lib/libcryptopp.so -shared -o /test/decoding.so
and the so object is created ok. If removed "-shared" compilation is OK but stops as no main in there (obviously ;) ). Of course libcryptopp.so exists too.
But when i go to python and import the "so" file, it said that the attribute has no object "decrypt", "encrypt" or whatever i put there. using "dir" over the dll objects confirms that they are not there.
external functions are defined in A.cpp as:
int encrypt (params...)
//..
return num;
int decrypt (params...)
//..
return num;
also tried using:
extern "C" encrypt (params...)
.....
Could anyone tell me what i'm doing wrong?
Thanks in advance!
Rag
C++ compiler mangles names of functions. To do what you are trying to do you must have the declaration prototype inside
extern "C" {...}
it's hard to tell from your samples what exactly you have in a source file.
As someone already mentioned, use nm utility to see what objects that are in your shared object.
Do not compile your object without -shared. Python load library does not support statically linked objects as far as am aware.
compile your object with g++ compiler instead, it will link to standard C++ Library, gcc does not.
just to doublecheck something since you using boost.
#include <string>
#include <boost/python.hpp>
using namespace std;
string hello(string s){
return "Hello World!";
}
BOOST_PYTHON_MODULE(pyhello){
using namespace boost::python;
def("hello", hello);
}
in python
>>> import pyhello
>>> print pyhello.hello()
Hello World!
just my 2 cents, sorry if this couldn't help you.

Trying to use/include/compile 3rd party library, libmagic. C/C++ filetype detection

After looking for a way to detect the filetype of a file stream, I found that the Unix file command uses libmagic and I'm trying to make use of the library myself, but I can't get it to work. I've rarely integrated 3rd party code in my own, so that's probably a big part of my problem as well.
Why:
I'm doing this because I have a portable gui image viewing app that will need to detect archive file types (rar, zip, more?) from given filename and then the image file types inside. I'm hoping that I can use libmagic for Windows and Linux (and Mac), so if this isn't the case, stop me now b/c I'll need to find something else.
Attempt:
I found somebody doing something similar, but I can't follow what they're doing, and I've no idea how compile/run anything at all to start messing around.
My first instinct was to do something like:
// fileTypeTest.cpp, placed in file-5.03/src/ (source from link above)
#include <stdio.h>
#include "magic.h"
int main() {
magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR/*|MAGIC_DEBUG*/|MAGIC_MIME);
magic_load(myt,NULL);
printf("magic output: '%s'\n",magic_file(myt,__FILE__));
magic_close(myt);
return 0;
}
then compile with something like:
$ gcc magic.c -o magic.o
$ g++ fileTypeTest.cpp -o fileTypeTest magic.o
which (obviously?) doesn't work. I don't even know where to start looking, what questions to ask, or if this is the right direction to go to solve my original problem in the first place.
Edit: Now I have
#include <stdio.h>
#include <magic.h>
int main(int argc, char* argv[]) {
if (argc != 2) {
printf("bad arguments");
return 0;
}
magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR/*|MAGIC_DEBUG*/|MAGIC_MIME);
magic_load(myt,NULL);
printf("magic output: '%s'\n", magic_file(myt, argv[1]));
magic_close(myt);
return 0;
}
compiling with:
$ g++ -L/usr/lib -libmagic fileTypeTest.cpp -o fileTypeTest
works. I had to go to synaptic and install libmagic-dev though. I'll have to test to see if I can just copy /usr/lib/libmagic.a into my source directory when compiling my app on Windows's MingW, but that'll be for another question later, I suppose.
__FILE__ is a reserved pre-processing symbol macro used for debugging/logging purposes. Consider this as an example:
// This file is called test.c
char *p = NULL;
if (!(p = malloc((1 * sizeof(char) + 1)))){
printf("Error in file: %s # line %d\n\tMalloc failed\n", __FILE__, __LINE__);
exit(-1);
}
If the call to malloc failed you will see the output in the above example like this:
Error in file: test.c # line 23
Malloc failed
Notice how the code picks up the original source code. The above example illustrates the usage of this.
I think your code should be something like this:
// fileTypeTest.cpp, placed in file-5.03/src/ (source from link above)
#include <stdio.h>
#include "magic.h"
int main(int argc, char **argv) {
if (argc > 1){
magic_t myt = magic_open(MAGIC_CONTINUE|MAGIC_ERROR/*|MAGIC_DEBUG*/|MAGIC_MIME);
magic_load(myt,NULL);
printf("magic output: '%s'\n",magic_file(myt,argv[1]));
magic_close(myt);
}
return 0;
}
The code above checks if there is a parameter that is passed into this program and the parameter would be a filename, i.e. argv[0] points to the executable name (the compiled binary), argv[1] points to the array of chars (a string) indicating the filename in question.
To compile it:
g++ -I/usr/include -L/usr/lib/libmagic.so fileTestType.cpp -o fileTestType
g++ -L/usr/lib -lmagic fileTestType.cpp -o fileTestType
Edit: Thanks Alok for pointing out the error here...
If you are not sure where the libmagic reside, look for it in the /usr/local/lib, and /usr/local/include - this depends on your installation.
See this to find the predefined macros here.
Hope this helps,
Best regards,
Tom.
Where is magic.h in the filesystem? Is the preprocessor finding it? If not, use -I<path>.
I don't know why you think the above "obviously" doesn't work. See How to mix C and C++ in the C++ FAQ for details.
Looks like magic.h has proper extern "C" { } enclosures. So, compiling your code with g++ should work nicely. You can #include <magic.h> in your .cpp file, and use all the libmagic functions.
Is there a particular error you're getting?
I have not checked your use of the libmagic functions.
You need to link with libmagic. Your g++ command needs -lmagic.
Since magic.h is most likely in a standard place, you should use #include <magic.h>.
Tell us what your error is for more specific help.