C++ CLI Class problem - c++-cli

----- hello, world 2.cpp -----
// Hello, World 2.cpp : main project file.
#include "stdafx.h"
#include "hello.h"
#include <string>
using namespace System;
using namespace std;
int main(array<System::String ^> ^args)
{
hello hi = new hello("Bob", "Blacksmith");
Console::WriteLine(L"Hello, " + hi.getName + "!");
return 0;
}
----- hello.h -----
#include <string>
using namespace std;
#ifndef HELLO_H
#define HELLO_H
class hello
{
private:
string _fname;
string _lname;
//hello() { } // private default constructor
public:
hello(string fname, string lname);
void SetName(string fname, string lname);
string GetName();
};
#endif
----- hello.cpp -----
#include "stdafx.h"
#include "hello.h"
#include <string>
using namespace std;
hello::hello(string fname, string lname)
{
SetName(fname, lname);
}
void hello::SetName(string fname, string lname)
{
_fname = fname;
_lname = lname;
}
string hello::getName()
{
return _fname + _lname;
}
----- The errors -----
------ Build started: Project: Hello, World 2, Configuration: Debug Win32 ------
Hello, World 2.cpp
Hello, World 2.cpp(12): error C2440: 'initializing' : cannot convert from 'hello *' to 'hello'
No constructor could take the source type, or constructor overload resolution was ambiguous
Hello, World 2.cpp(13): error C2039: 'getName' : is not a member of 'hello'
\documents\visual studio 2010\projects\cpp\hello, world 2\hello, world 2\hello.h(8) : see declaration of 'hello'
hello.cpp
hello.cpp(17): error C2039: 'getName' : is not a member of 'hello'
\documents\visual studio 2010\projects\cpp\hello, world 2\hello, world 2\hello.h(8) : see declaration of 'hello'
hello.cpp(19): error C2065: '_fname' : undeclared identifier
hello.cpp(19): error C2065: '_lname' : undeclared identifier
Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Error messages tell you exactly where and what the problems are, though they can be a bit intimidating at first. Maybe I can help demystify them a bit:
Hello, World 2.cpp(12): error C2440: 'initializing' : cannot convert from 'hello *' to 'hello'
This means that on line 12 in Hello, World 2.cpp, you're trying to put a pointer to hello (the return from new) inside hi which is not a pointer type. Since you don't need a dynamically allocated object here, just drop the new.
In situations where you do need a dynamically allocated object, you would change the hi variable to hello * and add a corresponding delete.
Hello, World 2.cpp(13): error C2039: 'getName' : is not a member of 'hello'
C++ is case sensitive. In one file you have GetName, in the other you have getName. Pick one.
hello.cpp(19): error C2065: '_fname' : undeclared identifier
hello.cpp(19): error C2065: '_lname' : undeclared identifier
Line 19 of hello.cpp is the definition of the lower case getName. Since getName wasn't declared in the class (see previous error), the compiler has no idea what _fname or _lname are. These errors will go away once the original problems are solved.
Edit
See #Sergey's answer for some other more general observations of things to fix.

The new keyword creates a pointer - if you do it this way, 'hi' should be declared as hello*, or you should reqrite the declaration as:
hello hi(...);
The second error is just due to case sensitivity (getName, GetName).

hello hi = new hello("William", "Dyson");
Must be
hello* hi = new hello(...);
Or
hello hi("William", "Dyson"); ;
Console::WriteLine(L"Hello, " + hi.getName + "!");
Must be
Console::WriteLine(L"Hello, " + hi.getName() + "!");
There may be other failures but i have to go now.

There are several errors.
File names with whitespaces. Not critical, but can lead to problems
Console::WriteLine(L"Hello, " + hi.getName + "!");
this should be something like this:
string s("Hello, ");
s += hi->getName();
s += "!"
Console::WriteLine(s);
delete objects allocated with new: delete hi;
string hello::getName() should be string hello::GetName()
Never use the use namespace ... in header files
Include other files within guard block

If you allocate something with new you have to call delete after you don't need it anymore.
In case you want to use the garbage collector the clean up for you you have to declare the class as ref class hello and then instantiate it with:
hello^ hi = gcnew hello(...);

Some comments that undoubtedly will be posted before I'm finished writing this:
Put you public members first
the namespace System implies Managed C++, if you don't know what that is and think you are using plain C++, please read about printf and std::cout.
The line
hello hi = new hello("William", "Dyson");
should read
hello hi("William", "Dyson"); or hello* hi = new hello("William", "Dyson");
The first creates an object on the stack (which will be automatically destructed as it goes out of scope. The second creates a pointer to an object on the heap, which you will have to delete before the pointer goes out of scope (after you've finished with it)
about hello::getName(): you have typos with regards to capitalization (getname vs getName) and it should be declared like this (in header and accordingly in the source file):
const string getName() const;
The first const is optional, but I like it that way, the last one lets you call this function from a const hello object, and tells the reader that the function does not modify the object.
You should pass string by reference (here is a correcter constructor):
hello( const string &fname, const string& lname);
Sources and headers should have names without spaces (or special characters) in them, this will be problematic for UNIX<->Windows if you're not careful.
That's all I can see right now.

Related

What's the protocol for calling Raku code from C code?

2023 update The last person to edit this Q deleted the critically important "LATEST LATEST UPDATE" part that #zentrunix had added near the top. I'm reinstating it.
LATEST LATEST UPDATE
Please see my answer below.
Thanks to everyone who took the time to answer and understand this question.
Original question
Say I have my event-driven TCP communications library in C.
From my Raku application, I can call a function in the C library using NativeCall.
my $server = create-server("127.0.0.1", 4000);
Now, from my callback in C (say onAccept) I want to call out to a Raku function in my application (say on-accept(connection) where connection will be a pointer to a C struct).
So, how can I do that: call my Raku function on-accept from my C function onAccept ?
ps. I tried posting using a simple title "How to call Raku code from C code", but for whatever reason stackoverflow.com wouldn't let me do it. Because of that I concocted this fancy title.
I was creating a 32-bit DLL.
We have to explicitly tell CMake to configure a 64-bit build.
cmake -G "Visual Studio 14 2015 Win64" ..
Anyway, now that the code runs, it's not really what I asked for, because the callback is still in C.
It seems that what I asked for it's not really possible.
I tried to use the approach suggested by Haakon, though I'm afraid I don't understand how it would work.
I'm in Windows, and unfortunately, Raku can't find my dlls, even if I put them in C:\Windows\System32. It finds "msvcrt" (C runtime), but not my dlls.
The dll code (Visual Studio 2015).
#include <stdio.h>
#define EXPORTED __declspec(dllexport)
typedef int (*proto)(const char*);
proto raku_callback;
extern EXPORTED void set_callback(proto);
extern EXPORTED void foo(void);
void set_callback(proto arg)
{
printf("In set_callback()..\n");
raku_callback = arg;
}
void foo(void)
{
printf("In foo()..\n");
int res = raku_callback("hello");
printf("Raku return value: %d\n", res);
}
Cmake code for the
CMAKE_MINIMUM_REQUIRED (VERSION 3.1)
add_library (my_c_dll SHARED my_c_dll.c)
Raku code.
use v6.d;
use NativeCall;
sub set_callback(&callback (Str --> int32))
is native("./my_c_dll"){ * }
sub foo()
is native("./my_c_dll"){ * }
sub callback(Str $str --> Int) {
say "Raku callback.. got string: {$str} from C";
return 32;
}
## sub _getch() returns int32 is native("msvcrt") {*};
## print "-> ";
## say "got ", _getch();
set_callback(&callback);
# foo();
When I run
$ raku test-dll.raku
Cannot locate native library '(null)': error 0xc1
in method setup at D:\tools\raku\share\perl6\core\sources
\947BDAB9F96E0E5FCCB383124F923A6BF6F8D76B (NativeCall) line 298
in block set_callback at D:\tools\raku\share\perl6\core\sources
\947BDAB9F96E0E5FCCB383124F923A6BF6F8D76B (NativeCall) line 594
in block <unit> at test-dll.raku line 21
Raku version.
$ raku -v
This is Rakudo version 2020.05.1 built on MoarVM version 2020.05
implementing Raku 6.d.
Another approach could be to save a callback statically in the C library, for example (libmylib.c):
#include <stdio.h>
static int (*raku_callback)(char *arg);
void set_callback(int (*callback)(char * arg)) {
printf("In set_callback()..\n");
raku_callback = callback;
}
void foo() {
printf("In foo()..\n");
int res = raku_callback("hello");
printf("Raku return value: %d\n", res);
}
Then from Raku:
use v6;
use NativeCall;
sub set_callback(&callback (Str --> int32)) is native('./libmylib.so') { * }
sub foo() is native('./libmylib.so') { * }
sub callback(Str $str --> Int) {
say "Raku callback.. got string: {$str} from C";
return 32;
}
set_callback(&callback);
foo();
Output:
In set_callback()..
In foo()..
Raku callback.. got string: hello from C
Raku return value: 32
Raku is a compiled language; depending on the implementation you've got, it will be compiled to MoarVM, JVM or Javascript. Through compilation, Raku code becomes bytecode in the corresponding virtual machine. So it's never, actually, binary code.
However, Raku code seems to be cleverly organized in a way that an object is actually a pointer to a C endpoint, as proved by Haakon Hagland answer.
WRT to your latest problem, please bear in mind that what you are calling is not a path, but a name that is converted to a navive shared library name and also uses local library path conventions to look for them (it's `PATH' on Windows). So if it's not finding it, add local path to it of simply copy the DLL to one of the searched directories.
First of all, my apologies to #Håkon and #raiph.
Sorry for being so obtuse. :)
Håkon's answer does indeed answer my question, although for whatever reason I have failed to see that until now.
Now the code I played with in order to understand Håkon's solution.
// my_c_dll.c
// be sure to create a 64-bit dll
#include <stdio.h>
#define EXPORTED __declspec(dllexport)
typedef int (*proto)(const char*);
proto raku_function;
extern EXPORTED void install_raku_function(proto);
extern EXPORTED void start_c_processing(void);
void install_raku_function(proto arg)
{
printf("installing raku function\n");
raku_function = arg;
}
void start_c_processing(void)
{
printf("* ----> starting C processing..\n");
for (int i = 0; i < 100; i++)
{
printf("* %d calling raku function\n", i);
int res = raku_function("hello");
printf("* %d raku function returned: %d\n", i, res);
Sleep(1000);
}
}
# test-dll.raku
use v6.d;
use NativeCall;
sub install_raku_function(&raku_function (Str --> int32))
is native("./my_c_dll.dll") { * }
sub start_c_processing()
is native("./my_c_dll.dll") { * }
sub my_raku_function(Str $str --> Int)
{
say "# raku function called from C with parameter [{$str}]";
return 32;
}
install_raku_function &my_raku_function;
start { start_c_processing; }
for ^1000 -> $i
{
say "# $i idling in raku";
sleep 1;
}
$ raku test-dll.raku
installing raku function
# 0 idling in raku
* ----> starting C processing..
* 0 calling raku function
# 0 raku function called from C with parameter [hello]
* 0 raku function returned: 32
# 1 idling in raku
* 1 calling raku function
# 1 raku function called from C with parameter [hello]
* 1 raku function returned: 32
# 2 idling in raku
* 2 calling raku function
# 2 raku function called from C with parameter [hello]
* 2 raku function returned: 32
# 3 idling in raku
* 3 calling raku function
# 3 raku function called from C with parameter [hello]
* 3 raku function returned: 32
# 4 idling in raku
* 4 calling raku function
# 4 raku function called from C with parameter [hello]
* 4 raku function returned: 32
# 5 idling in raku
* 5 calling raku function
# 5 raku function called from C with parameter [hello]
* 5 raku function returned: 32
^CTerminate batch job (Y/N)?
^C
What amazes me is that the Raku signature for my_raku_function maps cleanly to the C signature ... isn't Raku wonderful ? :)

transform javascript to opcode using spidermonkey

i am new to spider monkey and want to use it for transform java script file to sequence of byte code.
i get spider monkey and build it in debug mode.
i want to use JS_CompileScript function in jsapi.h to compile javascript code and analysis this to get bytecode , but when in compile below code and run it , i get run time error.
the error is "Unhandled exception at 0x0f55c020 (mozjs185-1.0.dll) in spiderMonkeyTest.exe: 0xC0000005: Access violation reading location 0x00000d4c." and i do not resolve it.
any body can help me to resolve this or introducing other solutions to get byte code from javascript code by using spider monkey ?
// spiderMonkeyTest.cpp : Defines the entry point for the console application.
//
#define XP_WIN
#include <iostream>
#include <fstream>
#include "stdafx.h"
#include "jsapi.h"
#include "jsanalyze.h"
using namespace std;
using namespace js;
static JSClass global_class = { "global",
JSCLASS_NEW_RESOLVE | JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub,
NULL,
JS_PropertyStub,
JS_StrictPropertyStub,
JS_EnumerateStub,
JS_ResolveStub,
JS_ConvertStub,
NULL,
JSCLASS_NO_OPTIONAL_MEMBERS
};
int _tmain(int argc, _TCHAR* argv[]) {
/* Create a JS runtime. */
JSRuntime *rt = JS_NewRuntime(16L * 1024L * 1024L);
if (rt == NULL)
return 1;
/* Create a context. */
JSContext *cx = JS_NewContext(rt, 8192);
if (cx == NULL)
return 1;
JS_SetOptions(cx, JSOPTION_VAROBJFIX);
JSScript *script;
JSObject *obj;
const char *js = "function a() { var tmp; tmp = 1 + 2; temp = temp * 2; alert(tmp); return 1; }";
obj = JS_CompileScript(cx,JS_GetGlobalObject(cx),js,strlen(js),"code.js",NULL);
script = obj->getScript();
if (script == NULL)
return JS_FALSE; /* compilation error */
js::analyze::Script *sc = new js::analyze::Script();
sc->analyze(cx,script);
JS_DestroyContext(cx);
JS_DestroyRuntime(rt);
/* Shut down the JS engine. */
JS_ShutDown();
return 1;
}
Which version of Spidermonkey are you using? I am using the one that comes with FireFox 10 so the API may be different.
You should create a new global object and initialize it by calling JS_NewCompartmentAndGlobalObject() and JS_InitStandardClasses() before compiling your script :
.....
/*
* Create the global object in a new compartment.
* You always need a global object per context.
*/
global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
if (global == NULL)
return 1;
/*
* Populate the global object with the standard JavaScript
* function and object classes, such as Object, Array, Date.
*/
if (!JS_InitStandardClasses(cx, global))
return 1;
......
Note, the function JS_NewCompartmentAndGlobalObject() is obsolete now, check the latest JSAPI documentation for the version your are using. Your JS_CompileScript() call just try to retrieve a global object which has not been created and probably this causes the exception.
how about using function "SaveCompiled" ? it will save object/op-code (compiled javascript) to file

How to make a pass that can read LLVM IR and parse it

I had read this page , http://llvm.org/docs/WritingAnLLVMPass.html
And i can do the example of the Hello.so completely.
Now i just want to make a .so file that can be called by opt and read my IR file name as input argument. And after i commit it , it will output the name of the file.
I had tried several methods before , but i still don't know how to do it....
I hope i can do it like this.
opt -load ../Debug+Asserts/lib/xxxx.so -flag < llvm.ll > /dev/null
when i press ENTER , it will output the name of the file -> "llvm.ll"
Can anyone help me write this simple program , i am going to optimize the llvm IR as my semester project , and now i stuck here ... help me , thanks ~
Can you tell me the code in detail , this doesn't work for me
using namespace llvm;
namespace {
struct Hello : public ModulePass {
static char ID;
Hello() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
dbgs() << M.getModuleIdentifier() << "\n";
return false;
}
};
}
char Hello::ID = 0;
static RegisterPass<Hello> X("hello", "Hello World Pass", false, false);
~
Your question could really be simplified to "how can I access the name of the current .ll file from within an LLVM pass". You don't need to "parse LLVM IR" or anything like that - when an LLVM pass is being ran it is already way past the parsing phase.
In any case, I'm not aware of any surefire way to get the filename from an LLVM module, but you can encode that information when you prepare the .ll file. For example, set the module id to be the filename via ; ModuleID = 'llvm.ll', then retrieve it by writing a module pass and invoking getModuleIdentifier to get the string. Then you could just print it out, e.g.
bool runOnModule(Module& M) {
dbgs() << M.getModuleIdentifier() << "\n";
return false;
}
Alternatively, use metadata.

Unknown type name 'namespace' in Xcode 4.2

I am compiling QCAR SDK, but it prompts an error after I added more frameworks to the project.
// Matrices.h
//
#ifndef _QCAR_MATRIX_H_
#define _QCAR_MATRIX_H_
namespace QCAR
{
/// Matrix with 3 rows and 4 columns of float items
struct Matrix34F {
float data[3*4]; ///< Array of matrix items
};
/// Matrix with 4 rows and 4 columns of float items
struct Matrix44F {
float data[4*4]; ///< Array of matrix items
};
} // namespace QCAR
#endif //_QCAR_MATRIX_H_
In the line namespace QCAR, it said Unknown type name 'namespace'.
What should I do?
UPDATE: Here is the build transcript
In file included from ../../build/include/QCAR/Tool.h:18:
In file included from /Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/ImageTargets/EAGLView.h:14:
In file included from /Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/ImageTargets/ImageTargetsAppDelegate.h:9:
In file included from /Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/CouponBook.m:12:
../../build/include/QCAR/Matrices.h:16:1: error: unknown type name 'namespace' [1]
namespace QCAR
^
../../build/include/QCAR/Matrices.h:16:15: error: expected ';' after top level declarator [1]
namespace QCAR
^
;
fix-it:"../../build/include/QCAR/Matrices.h":{16:15-16:15}:";"
In file included from /Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/ImageTargets/ImageTargetsAppDelegate.h:9:
In file included from /Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/CouponBook.m:12:
/Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/ImageTargets/EAGLView.h:52:5: error: type name requires a specifier or qualifier [1]
QCAR::Matrix44F projectionMatrix;
^
/Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/ImageTargets/EAGLView.h:52:10: error: expected expression [1]
QCAR::Matrix44F projectionMatrix;
^
/Users/Raptor.Kwok/Documents/xCodeProjects/qcar-ios-1-0-0/samples/ImageTargets/ImageTargets/EAGLView.h:52:5:{52:5-52:9}: warning: type specifier missing, defaults to 'int' [-Wimplicit-int,3]
QCAR::Matrix44F projectionMatrix;
^~~~
1 warning and 4 errors generated.
You can rename your file with .mm or you can select your .m file and change the "File Type" to "Objective-C++ Source".
I suspect the translation is C or Objective-C, where namespace is not a keyword as it is in C++ and Objective-C++.
Another possibility is that a previous header did not close a body (e.g. forgotten }; at end of class declaration of forgotten } at end of function definition).

gnokii: API error?

I have issues with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gnokii.h>
#define CONFIG_FILE "config"
struct gn_statemachine *state;
void terminate(void) {
gn_lib_phone_close(state);
gn_lib_phoneprofile_free(&state);
gn_lib_library_free();
}
int main() {
gn_data data;
gn_error error;
gn_sms_folder_list folderlist;
atexit(terminate);
if((error = gn_lib_phoneprofile_load(CONFIG_FILE,&state))
!= GN_ERR_NONE)
{
fprintf(stderr,"%s\n",gn_error_print(error));
exit(1);
}
memset(&folderlist,0,sizeof(gn_sms_folder_list));
gn_data_clear(&data);
data.sms_folder_list = &folderlist;
error = gn_sm_functions(GN_OP_GetSMSFolders, &data, state);
printf("ada %d sms dun\n",folderlist.number);
return 0;
}
I'm compiling it with gcc -o main main.c -lgnokii, but when it's executed it generates errors when looking for config file:
# ./gnokiitest
No phone_config section in the config file.
Either global or given phone section cannot be found.
Segmentation fault
because I included the config file within one folder of main output:
$ cat config
[global]
connection = bluetooth
port = 24:22:AB:AB:C1:F8
model = AT
rfcomm_channel = 2
Whats wrong then?
For starters, the following will cause issues:
if((error = gn_lib_phoneprofile_load(CONFIG_FILE,&state))
state variable is not initialized here. That will cause random pointer being passed and most likely segfault.
Next, the first argument to gn_lib_phoneprofile_load() is not the config file name, but the phone section in the config where the connection details are provided. Given that you pass config as this parameter you'd need:
[phone_config]
connection = bluetooth
port = 24:22:AB:AB:C1:F8
model = AT
rfcomm_channel = 2
but placed in the standard gnokii config file location. To use different location use:
gn_lib_phoneprofile_load_from_file(CONFIG_FILE, NULL, &state);
Second argument is the phone section name. If NULL, then [global] would be used.
Additionally gn_lib_phoneprofile_load() just reads the config file. You need to run gn_lib_phone_open() to initialize the connection.
Finally, there is similar code already written, no need to reinvent the wheel: http://git.savannah.gnu.org/cgit/gnokii/gnokii-extras.git/tree/snippets/sms/sms_status.c