As part of development for an application of mine that generates C source code, I need to be able to embed a compiler into my application so that it can generate executable object code. Since this is a sandboxed app intended for the Mac App Store, I cannot use NSTask to directly invoke clang, as the standalone tool apparently does not work under a sandbox. Pity.
I came across libclang, a library version of the compiler, which seems to do the trick. Using information from here, I was able to grab a preconfigured libclang binary to integrate into my application. Trouble is, I can't seem to figure out what the libclang API calls are that process and generate an executable. I found this sample code:
string source = "app.c";
string target= "app";
llvm::sys::Path clangPath = llvm::sys::Program::FindProgramByName("clang");
// arguments
vector<const char *> args;
args.push_back(clangPath.c_str());
args.push_back(source.c_str());
args.push_back("-l");
args.push_back("curl");
clang::TextDiagnosticPrinter *DiagClient = new clang::TextDiagnosticPrinter(llvm::errs(), clang::DiagnosticOptions());
clang::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs());
clang::DiagnosticsEngine Diags(DiagID, DiagClient);
clang::driver::Driver TheDriver(args[0], llvm::sys::getDefaultTargetTriple(), target, true, Diags);
clang::OwningPtr<clang::driver::Compilation> c(TheDriver.BuildCompilation(args));
int res = 0;
const clang::driver::Command *FailingCommand = 0;
if (c) res = TheDriver.ExecuteCompilation(*c, FailingCommand);
if (res < 0) TheDriver.generateCompilationDiagnostics(*c, FailingCommand);
Unfortunately, though, it won't compile. I get these errors:
Maybe I'm not including the right header files, I don't know. But given the lack off documentation for libclang, I would very much appreciate some help.
Related
How do I implement a function to load a dll(aka framework) on Mac OS using C++?
void LoadFramework(const char* frameworkPath)
{
//frameworkPath is the absolute path of the framework
}
Edit:
When I google searched for this problem, I mostly ended up with dlopen solution to load the framework. What I am instead looking for is to use CFBundleCreate to load the framework. It seems to me that there are a bunch of methods needed to be called to construct an URL from const char * path. I found the needed code in pieces, and could not write one comprehensive solution.
It typically is just a few lines of straightforward code to open a framework in Mac, something along the lines of :
bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
CFSTR("/System/Library/Frameworks/<your_framework_name.framework>"),
kCFURLPOSIXPathStyle, true);
bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL);
assert(bundle != NULL);
and pretty much everything in that snippet is well documented. I would suggest adding more detail in the question, as to the specifics of what exactly is not working for you.
Why not do this?
using DLL_Namespace;
This should give you access to the DLL.
In my application (Windows 10 VC2017) i enabled the possibility to write and execute scripts using google v8 and v8pp.
v8pp calls a script like this:
v8::Local<v8::Value> context::run_script(std::string const& source, std::string const& filename)
{
v8::EscapableHandleScope scope(isolate_);
v8::Local<v8::Context> context = isolate_->GetCurrentContext();
v8::ScriptOrigin origin(to_v8(isolate_, filename));
v8::Local<v8::Script> script;
bool const is_valid = v8::Script::Compile(context,
to_v8(isolate_, source), &origin).ToLocal(&script);
v8::Local<v8::Value> result;
if (!script.IsEmpty())
{
auto res1 = script->Run(context); //
if(! res1.IsEmpty())
result = res1.ToLocalChecked();
}
return scope.Escape(result);
}
How can i attach a debugger (chrome debug) to my code?
I found googles description at https://v8.dev/docs/inspector -
But this leaves some things blank and consists mostly of js code?
And i found the implementation for v8toolkit at https://github.com/xaxxon/v8toolkit/blob/master/src/debugger.cpp. But this seems to run not for windows.
What is a easy way to attach chrome debug to js code? The code is typically not a file but rather is stored in a data base and then stored in a std::string.
I finally got done a windows version of v8inspector that works well with my stand alone windows application with integrated v8.
I made a own fork including descriptions where to find/build the required 3rd party libraries (or where to find prebuilds). I also did a number of changes/additions:
https://github.com/StefanWoe/v8inspector
In the meanwhile this has also been merged into the parent project:
https://github.com/hsharsha/v8inspector
EDIT:
In the meanwhile ive been pointed to another implementation built with boost::beast and no other dependencies. Much simpler and more robust etc.:
https://github.com/ahmadov/v8_inspector_example
I know I should post this on the official RakNet forum, but I actually have, but it seems to be dead as hell.
The reason why I'm asking here is because I have no idea of C++, I'm a game developer and we're using Unity3D/C# to develop our new game, it's going to be Multiplayer and as RakNet was Open Sourced I wanted to give it a try.
So, here we go, this is the error log:
raknet_wrap.cxx(15441): error C2558: class 'RakNet::ReliabilityLayer' : no copy constructor available or copy constructor is declared 'explicit'
And the line where the error is is this:
jresult = new ReliabilityLayer((const ReliabilityLayer &)result);
Full function:
SWIGEXPORT void * SWIGSTDCALL CSharp_RakPeer_RemoteSystemStruct_reliabilityLayer_get(void * jarg1) {
void * jresult ;
RakNet::RakPeer::RemoteSystemStruct *arg1 = (RakNet::RakPeer::RemoteSystemStruct *) 0 ;
ReliabilityLayer result;
arg1 = (RakNet::RakPeer::RemoteSystemStruct *)jarg1;
result = ((arg1)->reliabilityLayer);
jresult = new ReliabilityLayer((const ReliabilityLayer &)result);
return jresult;
}
Can someone tell me why is it not working and explain it for a completely new person to C++ so I can understand the error?
(Edit) Going to also provide the ReliabilityLayer class! Here it is: http://pastebin.com/qTXedJFw
So I finally managed to build the RakNet C# DLL of the newest RakNet version.
And, as I don't want anybody with no experience on C++ to go through the madness I did through, I'm just sharing the DLL for easy use. Just import it to your project and start using it.
Here it is: https://drive.google.com/file/d/0BwuOJwLuDZfnM29DTFlLTWZWOXc/view?usp=sharing
OK to whoever is watching this and doesn't have a successful answer.
This is clearly a compiler bug in MSVC 2013 (that's what I tried).
SWIG generates the file 'RakNet_wrap.cxx' with the following line:
jresult = new ReliabilityLayer((const ReliabilityLayer &)result);
The quickest way around it is to edit this line so that it reads:
jresult = new ReliabilityLayer(result);
and hence the casting becomes implicit instead of explicit and MSVC 2013 accepts this.
The only problem is that when you hit Build, SWIG will overwrite this file and introduce the error again. So just remove the SWIG prebuild step (Alt+F7->Build Events->Pre-Build Event remove the PreBuild.bat from the command line) and build again. Now it will successfully compile and link as it should.
Don't forget to put the PreBuild.bat file again if you need to modify the source code and run SWIG again!
Also use SWIG 2.0.12; the latest version I tried (3.0.5); generates broken C# code (undefined HandleRef and IntPtr because System.Runtime.InteropServices is not either explicit nor imported via 'using' keyword).
I've raised a ticket to the SWIG project about this: https://github.com/swig/swig/issues/433
So...I have a kernel mode component and a user mode component I'm putting together using the turnkey build environment of the NT DDK 7.1.0. The kernel component is all .c/.h/.rc files. The user mode component is .cpp/.c/.h/.rc files.
At first it seemed simplest to use build for both, as I saw you could modify the ./sources file of the user mode component to say something like:
TARGETNAME = MyUserModeComponent
TARGETTYPE = PROGRAM
UMTYPE = windows
UMENTRY = winmain
USE_MSVCRT = 1
That didn't seem to cause a problem and so I was pleased, until I tried to #include <string> (or <memory>, or whatever) Doesn't find that stuff:
error C1083: Cannot open include file: 'string': No such file or directory
Still, it's compiling the user mode piece with C++ language semantics. But how do I get the standard includes to work?
I don't technically need to use the DDK build tool for the user mode piece. I could make a visual studio solution. I'm a bit wary as I have bumped into other annoyances, like the fact that the DDK uses __stdcall instead of __cdecl by default... and there isn't any pragma or compiler switch to override this. You literally have to go into each declaration you care about and change it, assuming you have source to do so. :-/
I'm starting to wonder if this is just a fractal descent into "just because you CAN doesn't mean you SHOULD build user mode apps with the DDK. Here be dragons." So my question isn't just about this particular technical hurdle, but rather if I should abandon the idea of building a C++ user mode component with the DDK tools...just because the kernel component is pure C.
To build a user mode program with WINDDK you need to add some variables to your SOURCES file:
386_STDCALL=0 to use cdecl calling convention by default
USE_STL=1 to use STL
USE_NATIVE_EH=1 to add a support for exception handling
Everything else you already have.
I'll put my full SOURCES file for reference:
TARGETNAME = MyUserModeComponent
TARGETTYPE = PROGRAM
TARGETPATH = obj
UMTYPE = console
UMENTRY = main
USE_MSVCRT = 1
USE_NATIVE_EH=1
USE_STL=1
386_STDCALL=0
SOURCES= main.cpp
And main.cpp:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s = "bla bla bla!";
cout << s;
return 0;
}
Have fun!
Quick Answer
Abandon the idea of building user-mode components with DDK tools (although I find the concept fascinating :-P)
Your kernel mode component should be built separately from the user mode components as a matter of good practice.
Vague thoughts
Off the top of my head, and this really speaking from limited experience...there are a lot of subtle differences that can creep up if you try to mix the two together.
Using your own example of __cdecl vs __stdcall; You have two different calling conventions. _cdecl is all kernel stuff and all of the C++ methods are wrapped around in WINAPI (_stdcall) passing conventions and __stdcall will clean do auto stack clean up and expect frame pointers inserted all over the place. And if you by accident use compiler options to trigger a __fastcall, it would be a pain to debug.
You can definitely hack something together, but do you really want to keep track of that in your user-space code and build environment? UGH I say.
Unless you have very specific engineering reasons to mix the two environments, (and no a unified build experience is not a valid reason, because you can get that from a batch file called buildall.bat) I say use the separate toolchains.
I'm looking for a simple example code for C++\IronPython integration, i.e. embedding python code inside a C++, or better yet, Visual C++ program.
The example code should include: how to share objects between the languages, how to call functions\methods back and forth etc...
Also, an explicit setup procedure would help too. (How to include the Python runtime dll in Visual Studio etc...)
I've found a nice example for C#\IronPython here, but couldn't find C++\IronPython example code.
UPDATE - I've written a more generic example (plus a link to a zip file containing the entire VS2008 project) as entry on my blog here.
Sorry, I am so late to the game, but here is how I have integrated IronPython into a C++/cli app in Visual Studio 2008 - .net 3.5. (actually mixed mode app with C/C++)
I write add-ons for a map making applicaiton written in Assembly. The API is exposed so that C/C++ add-ons can be written. I mix C/C++ with C++/cli. Some of the elements from this example are from the API (such as XPCALL and CmdEnd() - please just ignore them)
///////////////////////////////////////////////////////////////////////
void XPCALL PythonCmd2(int Result, int Result1, int Result2)
{
if(Result==X_OK)
{
try
{
String^ filename = gcnew String(txtFileName);
String^ path = Assembly::GetExecutingAssembly()->Location;
ScriptEngine^ engine = Python::CreateEngine();
ScriptScope^ scope = engine->CreateScope();
ScriptSource^ source = engine->CreateScriptSourceFromFile(String::Concat(Path::GetDirectoryName(path), "\\scripts\\", filename + ".py"));
scope->SetVariable("DrawingList", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingList::typeid));
scope->SetVariable("DrawingElement", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingElement::typeid));
scope->SetVariable("DrawingPath", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingPath::typeid));
scope->SetVariable("Node", DynamicHelpers::GetPythonTypeFromType(AddIn::Node::typeid));
source->Execute(scope);
}
catch(Exception ^e)
{
Console::WriteLine(e->ToString());
CmdEnd();
}
}
else
{
CmdEnd();
}
}
///////////////////////////////////////////////////////////////////////////////
As you can see, I expose to IronPython some objects (DrawingList, DrawingElement, DrawingPath & Node). These objects are C++/cli objects that I created to expose "things" to IronPython.
When the C++/cli source->Execute(scope) line is called, the only python line
to run is the DrawingList.RequestData.
RequestData takes a delegate and a data type.
When the C++/cli code is done, it calls the delegate pointing to the
function "diamond"
In the function diamond it retrieves the requested data with the call to
DrawingList.RequestedValue() The call to DrawingList.AddElement(dp) adds the
new element to the Applications visual Database.
And lastly the call to DrawingList.EndCommand() tells the FastCAD engine to
clean up and end the running of the plugin.
import clr
def diamond(Result1, Result2, Result3):
if(Result1 == 0):
dp = DrawingPath()
dp.drawingStuff.EntityColor = 2
dp.drawingStuff.SecondEntityColor = 2
n = DrawingList.RequestedValue()
dp.Nodes.Add(Node(n.X-50,n.Y+25))
dp.Nodes.Add(Node(n.X-25,n.Y+50))
dp.Nodes.Add(Node(n.X+25,n.Y+50))
dp.Nodes.Add(Node(n.X+50,n.Y+25))
dp.Nodes.Add(Node(n.X,n.Y-40))
DrawingList.AddElement(dp)
DrawingList.EndCommand()
DrawingList.RequestData(diamond, DrawingList.RequestType.PointType)
I hope this is what you were looking for.
If you don't need .NET functionality, you could rely on embedding Python instead of IronPython. See Python's documentation on Embedding Python in Another Application for more info and an example. If you don't mind being dependent on BOOST, you could try out its Python integration library.