How do I correctly call Poco functions from managed C++ code? - clr

I'm using pocoXML functions in a managed DLL, which is used by another managed C++ project. The managed DLL compiles perfectly. But when calling a DLL-function which uses a poco function, I get a Debug Assertion Fail (is_block_type_valid) in debug_heap.cpp.
//managed DLL code:
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
class __declspec(dllexport) log
{
public:
static void Log(const char* source, const char* file, const char* function, const std::string& str = "");
}
void log::Debug(const char* file, const char* function, const std::string& str)
{
const Poco::Timestamp now;
const std::string time = Poco::DateTimeFormatter::format(now, Poco::DateTimeFormat::ISO8601_FRAC_FORMAT);
std::stringstream log;
log << "[" << time.c_str() << "; Debug]: " << methodname(file, function) << " - " << str;
std::string str = log.str();
fprintf(stdout, "%s\n", str.c_str());
}
//call from managed C++:
log::Debug(__FILE__, __FUNCTION__, "message");
What am I doing wrong?
Thanks!

Seems, that Poco Lib was compiled for Windows SDK 8.1 instead of 10.
A recompilation with right SDK set solved the problem.

Related

array<double*> to vector<double> range v3 style on VS2019

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";
}

How to pass a file stream as an argument to a Rcpp-function?

I am new to Rcpp. My problem: I want to have a function (writeToFile) that writes to a file on my hard drive.
This function shall be called several times within a second function (foo). Thus I want to open the stream only once, write to the file and close the stream.
What I've already learned: In C++ streams need to be passed by reference.
My code, however, where the argument myfile is passed by reference does not compile:
#include <Rcpp.h>
#include <fstream>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
void writeToFile (ostream& myfile, string text) {
myfile << text << "\n";
}
// [[Rcpp::export]]
void foo (string text, int n, string file = "example.txt") {
ofstream myfile;
myfile.open(file.c_str());
for (int i = 0; i < n; i++) {
writeToFile(myfile, text);
}
}
I get the error message:
std::basic_ostream<_CharT, _Traits>::basic_ostream(std::basic_ostream<<_CharT, _Traits>&&) [with _CharT = char; _Traits = std::char_traits<char>]' is protected within this context.
Any tips what I'm doing wrong?

Usage of FunctionPass over ModulePass when creating LLVM passes

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.

rewrite codes which matches a certain ASTMatcher

I'm new to clang and I want to rename member variable name using ASTMatcher. For example:
class Person
{
public:
....
private:
char m_genger;
^^^^^^^^ => rename to gender_
int m_age;
^^^^^^ => rename to age_
};
After reading some tutorials now I found how to use ASTMatcher, so that I can access location to be modified.
But I got a Seg. Fault right after calling clang::Rewriter::ReplaceText or InsertText.
My ASTMatcher Program
DeclarationMatcher FieldDeclMatcher =
clang::ast_matchers::fieldDecl().bind("field_decl");
clang::Rewriter rewriter;
class MyMatcher : public MatchFinder::MatchCallback
{
public :
MyMatcher(clang::Rewriter& rewrite) : m_rewriter(rewrite) {}
virtual void run(const MatchFinder::MatchResult& result)
{
if (const clang::FieldDecl* fs
= result.Nodes.getNodeAs<clang::FieldDecl>("field_decl"))
{
std::cout << "===== found: FieldDecl =====" << std::endl;
fs->dump();
std::cout << std::endl;
// seg. fault occurs here.
m_rewriter.InsertText(fs->getLocStart(), "/* comment */", true, true);
}
}
private:
clang::Rewriter& m_rewriter;
};
int main(int argc, const char **argv)
{
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
MyMatcher matcher(rewriter);
clang::ast_matchers::MatchFinder finder;
finder.addMatcher(FieldDeclMatcher, &matcher);
return Tool.run(newFrontendActionFactory(&finder).get());
}
Output of gdb backtrace
#0 0x0000000000a52153 in clang::Rewriter::getLocationOffsetAndFileID(clang::SourceLocation, clang::FileID&) const ()
#1 0x0000000000a5516a in clang::Rewriter::InsertText(clang::SourceLocation, llvm::StringRef, bool, bool) ()
#2 0x0000000000422f0d in MyMatcher::run(clang::ast_matchers::MatchFinder::MatchResult const&) () at ex03.cc:68
Thanks.
After reading Eli Bendersky's post, I found the answer.
It seems like that I can't rewrite codes only using ASTMatcher, To modify code, we need not only ASTFrontendAction and ASTConsumer but ASTMatcher.
(please correct me, if I'm wroing)
You can get Eli's code his github repository.

GNU Guile SCM to char*

I am relative new to FFI and GNU Guile, and I am writing bindings to a library that heavily uses char* variables. Here is code from function, that wraps C function:
static inline char*
scm_to_ascii_string(SCM string)
{
return SCM_UNBNDP(SCM) ? NULL
: scm_to_stringn(string, NULL, "ascii", SCM_FAILED_CONVERSION_ERROR);
}
SCM_DEFINE(func, "func", ...)
{
...
char *server_pass = scm_to_ascii_string(scm_server_pass);
char *username = scm_to_ascii_string(scm_username);
char *realname = scm_to_ascii_string(scm_realname);
}
Problem is that any call to conversion function can throw error, leaving me with memory leak.
What can I do about it?
You could make the output part an argument eg:
void scm_to_ascii_string(SCM string, char* &out);
edit:
I guess you meant what exception handler methods are there on the c side, I think there might be something on that in the manual in one of the two sections on programming stuff in C.

Resources