I want to make a custom vapi file, I have the basic stuff but I obviously miss something and I can't find anywhere how to do this properly. My main goal is to create a torent app, using libtorrent, and create the GUI (the frontend?) with vala and gtk.
I have a c_func_head.h:
#ifndef WHATEVER_H_INCLUDED
#define WHATEVER_H_INCLUDED
int add(int a, int b);
#endif
c_functions.c:
#include <stdio.h>
#include <stdlib.h>
#include "c_func_head.h"
int add(int a, int b){
printf("Adding numbers in c...\n");
return a+b;
}
vala_p.vapi:
[CCode (cheader_filename = "c_func_head.h")]
namespace MyFunc {
[CCode (cname = "add")]
public int add (int a, int b);
}
and finally vala_program.vala:
//extern int add(int a, int b);
using MyFunc;
void main(){
stdout.printf("Calling a c function...\n");
//stdout.printf("The sum is: %d\n", add2number(2, 2));
int sum = add(2, 2);
stdout.printf("The sum is: %d\n", sum);
}
As you can see I used an extern too, it worked with it but I want to use vapi files.
I compiled with (everything is in the same folder):
valac vala_program.vala --vapidir=vala_p.vapi -o mustrun
and the error is:
The namespace name `MyFunc' could not be found using MyFunc;
One more thing. Is it possible to make bindings for libtorrent? It uses c++ and I gues I have to use c++ too.
You can't make Vala bindings of C++ code. Only C. There a a guide to writing legacy bindings and a binding for Transmission, which is C-based.
As for the specific error you have, you want to call valac vala_program.vala vala_p.vapi if the library (i.e., header files) are the the same directory or valac vala_program.vala --pkg vala_p --vapidir=/path/to/directory/containing/vapi.
Related
I want to convert an array<double*> to a vector<double> so that I can do a ranges::views::concat on two vectors of the same type but I'm having difficulty doing this.
I have the following code:
#include <range/v3/all.hpp>
#include <array>
static constexpr auto max_elements = 2000;
struct PriceInfo
{
std::array<double*, max_elements> prices;
};
auto main() -> int
{
const PriceInfo* const buf_prices = nullptr;
const auto vec = buf_prices->prices
| ranges::views::indirect
| ranges::to_vector;
}
When I compile I'm getting the following errors and I don't understand why as I believe my code is correct, at least it compiles errorfree under gcc.
Error (active) E0349 no operator "|" matches these operands
How do I fix this error please?
FIrst of, your code contains UB, because you had never created PriceInfo.
Second, the error may mean incorrect project configuration, is standard set? is compiler fully compatible with requirements of library? Is it proper fork of library, if that's the case (e.g. there were separate forks for MSVC compilers).
Third, assuming those problems will be solved, this code would segfault unless ALL elements of prices are non-nullptr.
This way it works:
#include <range/v3/all.hpp>
#include <iostream>
#include <array>
static constexpr auto max_elements = 3; // will segfault if there are null pointers
struct PriceInfo
{
std::array<double*, max_elements> prices;
};
auto main() -> int
{
auto a = std::array<double,3>{1.0, 2.0, 3.0};
const PriceInfo* const buf = new PriceInfo{&a[0], &a[1], &a[2]};
const auto vec = buf->prices
| ranges::views::indirect
| ranges::to_vector;
for( auto a : vec)
std::cout << a << "\n";
}
I've seen quite a numerous amount of examples that go over creating functions passes (e.g. Brandon Holt and Adrian Sampson), but I am curious as to the difficulty in creating a module pass to do these very similar problems. I've tried to implement a module pass to display the global variable names using this example and llvm source code to understand how you have to iterate through members.
I am using a source compiled version of LLVM, and using the example from the above links to add the pass, and then running:
$ clang -Xclang -load -Xclang build/Skeleton/libSkeletonPass.so something.c
Which then returns this gibberish. However, if I implement a functionPass and just use Auto to determine the type to be initialized it's very straight forward and works. Am I just going about printing the global variables the wrong way?
This is a pastebin of the error output from the terminal. link
Skeleton.cpp
#include "llvm/Pass.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/LLVMContext.h"
using namespace llvm;
namespace {
// Helper method for converting the name of a LLVM type to a string
static std::string LLVMTypeAsString(const Type *T) {
std::string TypeName;
raw_string_ostream N(TypeName);
T->print(N);
return N.str();
}
struct SkeletonPass : public ModulePass {
static char ID;
SkeletonPass() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) {
for (Module::const_global_iterator GI = M.global_begin(),
GE = M.global_end(); GI != GE; ++GI) {
errs() << "Found global named: " << GI->getName()
<< "\tType: " << LLVMTypeAsString(GI->getType()) << "!\n";
}
return false;
}
};
}
char SkeletonPass::ID = 0;
// Automatically enable the pass.
// http://adriansampson.net/blog/clangpass.html
static void registerSkeletonPass(const PassManagerBuilder &,
legacy::PassManagerBase &PM) {
PM.add(new SkeletonPass());
}
static RegisterStandardPasses
RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible,
registerSkeletonPass);
something.c
int value0 = 5;
int main(int argc, char const *argv[])
{
int value = 4;
value += 1;
return 0;
}
I was able to figure this out after some extensive github searching. Here is the answer from which I was following a tutorial to help others who may be curious how to implement a Module Pass.
I'm new to llvm , and was trying to find lock declaration statement and then do some instrumention work,the code like this:
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int share = 42;
mutex m;
void f()
{
m.lock();
--share;
cout << "function f -> share: " << share << '\n';
m.unlock();
}
int main()
{
thread thf{f};
thf.join();
return 0;
}
I want to find the lock declaration instruction eg:
mutex m;
the llvm instrumention pass like this:
struct SkeletonPass : public FunctionPass {
static char ID;
SkeletonPass() : FunctionPass(ID) {}
virtual bool runOnFunction(Function &F) {
// Get the function to call from our runtime library.
LLVMContext &Ctx = F.getContext();
Constant *logFunc = F.getParent()->getOrInsertFunction(
"logop", Type::getVoidTy(Ctx), Type::getInt32Ty(Ctx), NULL
);
for (auto &B : F) {
for (auto &I : B) {
***if ((&I) is lock declaration instruction)*** {
// Insert something *after* `op`.
IRBuilder<> builder(op);
builder.SetInsertPoint(&B, ++builder.GetInsertPoint());
// Insert a call to function.
builder.CreateCall(logFunc, ConstantInt::get(Type::getInt32Ty(Ctx), 2));
return true;
}
}
}
In short, could you please tell me how to discover lock declaration instruction, thanks!
The declaration would appear as a global, so you should write a module pass to find it, not a function pass. It should appear as something like:
#m = global %mutex zeroinitializer
In fact, using the demo at http://ellcc.org/demo/index.cgi to try this, you can indeed see that:
...
%"class.std::__1::mutex" = type { %struct.pthread_mutex_t }
%struct.pthread_mutex_t = type { %union.anon }
%union.anon = type { [5 x i8*] }
...
#m = global %"class.std::__1::mutex" zeroinitializer, align 8
You can use LLVM's CppBackend to compile your code. This would produce a C++ code that makes up the source. You can then easily find out how mutex m; definition is constructed via LLVM API.
Run clang -march=cpp foo.cpp to use CppBackend. Alternatively, you can use this demo page to compile your code online.
I have this simple program which i make into dll in Visual C++ 2008 Express:
#include <lua52/lua.h>
#include <lua52/lualib.h>
#include <lua52/lauxlib.h>
#pragma comment(lib,"lua52.lib")
#include <stdio.h>
int needless(lua_State *L)
{
printf("bullshit\n");
return 0;
}
static const struct luaL_Reg noise[] = {
{"needless",needless},
{NULL,NULL}
};
__declspec(dllexport) int __cdecl luaopen_noise(lua_State *L)
{
luaL_newlib(L, noise);
return 1;
}
when I link the resulting dll with "import noise" in lua5.2 interpreter, I get that "multiple lua VMs detected" for reason that eludes me. What should I do to fix make it work?
Lua libraries written in C should not include a copy of the Lua core library.
I don't know Visual C+ but this line is probably the culprit:
#pragma comment(lib,"lua52.lib")
I decided to add scripting with Lua. I've downloaded and compiled interpreter. It works fine, but when I want to use any functions from os.* or string.* libs, it says, that "attemt to index global 'os' (a nil value)"
Here is my code and should work, but it does not:
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
extern "C" {
#include "..\liblua\lua.h"
#include "..\liblua\lualib.h"
#include "..\liblua\lauxlib.h"
}
int main(int argc, TCHAR* argv[])
{
lua_State *LuaVM = luaL_newstate();
lua_pushcfunction(LuaVM,luaopen_base);
lua_call(LuaVM,0,0);
lua_pushcfunction(LuaVM,luaopen_math);
lua_call(LuaVM,0,0);
lua_pushcfunction(LuaVM,luaopen_string);
lua_call(LuaVM,0,0);
lua_pushcfunction(LuaVM,luaopen_table);
lua_call(LuaVM,0,0);
int error;
lua_pushstring(LuaVM,"Ver 0.525.5");
lua_setglobal(LuaVM,"Version");
while (true)
{
string strCode;
getline(cin,strCode);
error = luaL_loadbuffer(LuaVM,strCode.c_str(),strCode.length(),"") ||
lua_pcall(LuaVM,0,0,0);
if (error)
{
cout<< lua_tostring(LuaVM,-1)<<endl;
lua_pop(LuaVM,1);
}
}
lua_close(LuaVM);
return 0;
}
What's wrong with it?
In Lua 5.2 the standard luaopen_* functions do not set the corresponding global variables.
Why not copy and adapt the code in linit.c or just call luaL_openlibs?
Otherwise, do what they do: call luaL_requiref for each luaopen_* function.
See http://www.lua.org/source/5.2/linit.c.html#luaL_openlibs.