So I'm trying to load a .dylib file at runtime in c++ and calling a function within it. It does not seem to be any problem loading the file but when i try to create a function-pointer to the "print" function it's result is NULL.
Here is my code:
/* main.cpp */
#include <iostream>
#include <string>
#include <dlfcn.h>
#include "test.hpp"
int main(int argc, const char * argv[]) {
std::string path = argv[0];
std::size_t last = path.find_last_of("/");
// get path to execution folder
path = path.substr(0, last)+"/";
const char * filename = (path+"dylibs/libtest.dylib").c_str();
// open libtest.dylib
void* dylib = dlopen(filename, RTLD_LAZY);
if (dylib == NULL) {
std::cout << "unable to load " << filename << " Library!" << std::endl;
return 1;
}
// get print function from libtest.dylib
void (*print)(const char * str)= (void(*)(const char*))dlsym(dylib, "print");
if (print == NULL) {
std::cout << "unable to load " << filename << " print function!" << std::endl;
dlclose(dylib);
return 2;
}
// test the print function
print("Herro Word!");
dlclose(dylib);
return 0;
}
test dylib headerfile
/* test.hpp */
#ifndef test_hpp
#define test_hpp
void print(const char * str);
#endif
the dylib c++ file
#include <iostream>
#include "test.hpp"
void print(const char * str) {
std::cout << str << std::endl;
}
the output when running is:
unable to load /Users/usr/Library/Developer/Xcode/DerivedData/project/Build/Products/Debug/dylibs/libtest.dylib print function!
Program ended with exit code: 2
I am quite new to c++ and have never loaded dylibs before. Any help would be much appreciated!
Try qualifying the print function declaration with extern "C" to get around the name mangling that is likely going on.
Here's a nice article on the topic: http://www.tldp.org/HOWTO/C++-dlopen/theproblem.html (solution discussion on page following)
Related
In my program I use an external function which generates output to me and I don't want it not to be generated by that function alone,
it's possible?
int main()
{
int a;
//I don't want the output of this function
a = function();
//now i want output
cout << "the result is : " << a;
}
Is it possible?
EDIT:
The function is in an external library.
Using only standard C++ where no dup-like functions exist, you could open a temporary std::FILE and std::swap with stdout.
#include <cerrno>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
// extern "C" int function(); // an assumption
// A helper class to temporarilly redirect the output to stdout to a file and to read
// the content of the file afterwards.
class BufferStdout {
public:
// the collector string is used for collecting the output to stdout
BufferStdout (std::string& collector) :
m_collector(collector),
fp(std::fopen("output.txt", "w"))
{
if(fp == nullptr) throw std::runtime_error(std::strerror(errno));
std::swap(stdout, fp); // swap stdout and the temp file
}
~BufferStdout () {
std::swap(stdout, fp); // swap back
std::fclose(fp);
// read the content of the temp file into m_collector
if(std::ifstream is("output.txt"); is) {
m_collector.append(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>{});
}
std::remove("output.txt"); // cleanup
}
private:
std::string& m_collector;
std::FILE* fp;
};
int main() {
std::string collector; // the string that will contain the output from function()
int a;
{
BufferStdout foo(collector);
a = function();
}
std::cout << "the result is : " << a << '\n';
std::cout << "Collected from function():\n";
std::cout << collector << '\n';
}
Yes it is generally possible but a bit complicated, a similar question is in Suppress output to cout from linked library
In addition to you can redirect stdout before invoking the shared library function and then redirect it again after the use of the shared library function in the however this is also a suboptimal solution. Best solution would be to adapt the shared library
// Cpp program to redirect cout to a file
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
fstream file;
file.open("cout.txt", ios::out);
string line;
// Backup streambuffers of cout
streambuf* stream_buffer_cout = cout.rdbuf();
streambuf* stream_buffer_cin = cin.rdbuf();
// Get the streambuffer of the file
streambuf* stream_buffer_file = file.rdbuf();
// Redirect cout to file
cout.rdbuf(stream_buffer_file);
cout << "This line written to file" << endl;
// Redirect cout back to screen
cout.rdbuf(stream_buffer_cout);
cout << "This line is written to screen" << endl;
file.close();
return 0;
}
Note: The above steps can be condensed into a single step
auto cout_buf = cout.rdbuf(file.rdbuf())
// sets couts streambuffer and returns the old
streambuffer back to cout_buf
source : https://www.geeksforgeeks.org/io-redirection-c/
use
fclose(stdout);
with this function you will suppress any printf inside your libraries.
Of course you can not print other stuff inside your software.
I want to create a C++ program that loads a dll(a.dll). It should run in
combination with wine in Linux. In the dll a function foo will be called
which takes two strings and an integer. foo returns an integer. The dll
is located in the same directory as the exe. Unfortunately the dll file
is not found and I don't know why. I have also tried "./a.dll" under
Linux. Can anyone give me some advice on this?
#include <iostream>
#include <string>
#include "windows.h"
#include <tchar.h>
typedef int(*func_ptr)(std::string, std::string, int);
int main()
{
func_ptr function1 = NULL;
HMODULE hGetProcIDDLL = LoadLibrary(L"a.dll");
if (hGetProcIDDLL != NULL)
{
std::cout << "Found!";
}
else
{
std::cout << "File not found!";
return 0;
}
function1 = (func_ptr)GetProcAddress(hGetProcIDDLL, "foo");
if (function1 != NULL)
{
std::cout << function1("input-file.txt","output-file.txt",0);
}
else
{
std::cout << "Function not found";
}
FreeLibrary(hGetProcIDDLL);
std::cin.get();
return(0);
}
What am I missing here, this is my main program, I also have a makefile and everything works the error is somewhere in here.
#include <iostream>
#include <observer.h>
#include <fstream>
using namespace std;
int main(int argc, char* argv[]) {
std::fstream in;
int gettimeofday;
//CPUtypeandmodel
struct timeval now;
gettimeofday(&now, NULL);
cout << "Status report as of : " << ctime((time_t*)&now.tv_sec) << endl;
// Print machine name
in.open("/proc/sys/kernel/hostname");
string s;
in >> s;
cout << "Machine name: " << s << endl;
in.close();
return 1;
} //end main
When I try and make the file this happens
observer.cpp: In function ‘int main(int, char**)’:
observer.cpp:13:26: error: ‘gettimeofday’ cannot be used as a function
gettimeofday(&now, NULL);
^
<builtin>: recipe for target 'observer.o' failed
make: *** [observer.o] Error 1
You named a local int variable gettimeofday, which prevents you from calling the function gettimeofday() three lines later. Don't do that. Name the variable something else, or (given it seems unused) just get rid of it.
Your int gettimeofday; is shadowing the function with the same name. You don't even need that variable so remove it.
You need to include ctime and sys/time.h for the functions and classes you use.
You open the file /proc/sys/kernel/hostname for writing, which will fail unless you run the program as root.
The casting to time_t* is not necessary since &now.tv_sec is already a time_t*.
#include <sys/time.h>
#include <ctime>
#include <fstream>
#include <iostream>
#include <string>
int main() {
// CPUtypeandmodel
timeval now;
if(gettimeofday(&now, nullptr) == 0) // check for success
std::cout << "Status report as of : " << std::ctime(&now.tv_sec) << '\n';
// Print machine name
if(std::ifstream in("/proc/sys/kernel/hostname"); in) { // open for reading
std::string s;
if(in >> s) // check for success
std::cout << "Machine name: " << s << '\n';
} // no need to call in.close(), it'll close automatically here
return 1; // This usually signals failure. Return 0 instead.
} // end main
So I was trying to make a program that dynamically creates a dll file and loads it into the program and calls it.
Here is my code for
createFile:
void createFile(std::string data, std::string name) {
std::ofstream file;
name += ".cpp";
file.open(name,std::ofstream::out);
if (file.is_open()) {
file << data;
std::cout << "File saved successfully" << std::endl;
file.close();
}
else {
std::cout << "Error opening file" << std::endl;
exit(1);
}
}
compile:
void compile(std::string name) {
std::string temp;
temp = "c++.exe " + name + ".cpp -o dll/" + name + ".dll -shared -fPIC";
system(temp.c_str());
}
loadFunc:
typedef void (*function)(const char*);
void loadFunc(LPCSTR name, LPCSTR func) {
HMODULE temp;
function __cdecl myproc;
temp = LoadLibraryA(name);
if (temp != NULL) {
std::cout << "\nDll is loaded";
myproc = (function) GetProcAddress(temp, func);
if (myproc !=NULL)
{
std::cout << "\nFunction is loaded\n";
(myproc)("Somthing here");
}
// Free the DLL module.
FreeLibrary(temp);
}
}
The problem is when I compile a dll using visual studio 2019 it works just fine, but if I compile a dll file using gcc or c++ or g++ it doesn't load the dll. So I tried using dependency walker to see the difference between two dll files(one made with gcc and another with visual studio). I saw the file structures were different. dll made with gcc had larger size than the one made with visual studio. Can anyone help me with this?
Edit:
So after doing some trial and error, I have found that only dll files that have C libraries work. I don't know why. I tried using iostream earlier, but it always failed to load and on the other hand when I used stdio.h it worked fine.
dllfile.cpp(with iostream):
#ifdef __cpluplus
extern "C" {
#endif
#include <iostream>
__declspec(dllexport) void print(const char *x){
std::cout<<x<<std::endl;
}
#ifdef __cplusplus
}
#endif
dllfile.cpp(with stdio):
#ifdef __cpluplus
extern "C" {
#endif
#include <stdio.h>
__declspec(dllexport) void print(const char *x){
printf("%s",x);
}
#ifdef __cplusplus
}
#endif
I am trying to use clang+llvm 3.6 to JIT compile several C functions (each can eventually be very large).
Unfortunately I the function pointer that LLVM provides makes the program SEGFAULT.
So far I have following code:
#include <iostream>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Basic/DiagnosticOptions.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/FrontendDiagnostic.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Frontend/Utils.h>
#include <clang/Parse/ParseAST.h>
#include <clang/Lex/Preprocessor.h>
#include <llvm/Analysis/Passes.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/IR/Verifier.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/raw_os_ostream.h>
#include <llvm/Linker/Linker.h>
int main(int argc, char *argv[]) {
using namespace llvm;
using namespace clang;
static const char* clangArgv [] = {"program", "-x", "c", "string-input"};
static const int clangArgc = sizeof (clangArgv) / sizeof (clangArgv[0]);
// C functions to be compiled (they could eventually be extremely large)
std::map<std::string, std::string> func2Source;
func2Source["getOne"] = "int getOne() {return 1;}";
func2Source["getTwo"] = "int getTwo() {return 2;}";
llvm::InitializeAllTargets();
llvm::InitializeAllAsmPrinters();
std::unique_ptr<llvm::Linker> linker;
std::unique_ptr<llvm::LLVMContext> context(new llvm::LLVMContext());
std::unique_ptr<llvm::Module> module;
/**
* add each C function to the same module
*/
for (const auto& p : func2Source) {
const std::string& source = p.second;
IntrusiveRefCntPtr<DiagnosticOptions> diagOpts = new DiagnosticOptions();
TextDiagnosticPrinter *diagClient = new TextDiagnosticPrinter(llvm::errs(), &*diagOpts); // will be owned by diags
IntrusiveRefCntPtr<DiagnosticIDs> diagID(new DiagnosticIDs());
IntrusiveRefCntPtr<DiagnosticsEngine> diags(new DiagnosticsEngine(diagID, &*diagOpts, diagClient));
ArrayRef<const char *> args(clangArgv + 1, // skip program name
clangArgc - 1);
std::unique_ptr<CompilerInvocation> invocation(createInvocationFromCommandLine(args, diags));
if (invocation.get() == nullptr) {
std::cerr << "Failed to create compiler invocation" << std::endl;
exit(1);
}
CompilerInvocation::setLangDefaults(*invocation->getLangOpts(), IK_C,
LangStandard::lang_unspecified);
invocation->getFrontendOpts().DisableFree = false; // make sure we free memory (by default it does not)
// Create a compiler instance to handle the actual work.
CompilerInstance compiler;
compiler.setInvocation(invocation.release());
// Create the compilers actual diagnostics engine.
compiler.createDiagnostics(); //compiler.createDiagnostics(argc, const_cast<char**> (argv));
if (!compiler.hasDiagnostics()) {
std::cerr << "No diagnostics" << std::endl;
exit(1);
}
// Create memory buffer with source text
std::unique_ptr<llvm::MemoryBuffer> buffer = llvm::MemoryBuffer::getMemBufferCopy(source, "SIMPLE_BUFFER");
if (buffer.get() == nullptr) {
std::cerr << "Failed to create memory buffer" << std::endl;
exit(1);
}
// Remap auxiliary name "string-input" to memory buffer
PreprocessorOptions& po = compiler.getInvocation().getPreprocessorOpts();
po.addRemappedFile("string-input", buffer.release());
// Create and execute the frontend to generate an LLVM bitcode module.
clang::EmitLLVMOnlyAction action(context.get());
if (!compiler.ExecuteAction(action)) {
std::cerr << "Failed to emit LLVM bitcode" << std::endl;
exit(1);
}
std::unique_ptr<llvm::Module> module1 = action.takeModule();
if (module1.get() == nullptr) {
std::cerr << "No module" << std::endl;
exit(1);
}
if (linker.get() == nullptr) {
module.reset(module1.release());
linker.reset(new llvm::Linker(module.get()));
} else {
if (linker->linkInModule(module1.release())) {
std::cerr << "LLVM failed to link module" << std::endl;
exit(1);
}
}
}
llvm::InitializeNativeTarget();
llvm::Module* m = module.get();
std::string errStr;
std::unique_ptr<llvm::ExecutionEngine> executionEngine(EngineBuilder(std::move(module))
.setErrorStr(&errStr)
.setEngineKind(EngineKind::JIT)
.setMCJITMemoryManager(std::unique_ptr<SectionMemoryManager>(new SectionMemoryManager()))
.setVerifyModules(true)
.create());
if (!executionEngine.get()) {
std::cerr << "Could not create ExecutionEngine: " + errStr << std::endl;
exit(1);
}
executionEngine->finalizeObject();
/**
* Lets try to use each function
*/
for (const auto& p : func2Source) {
const std::string& funcName = p.first;
llvm::Function* func = m->getFunction(funcName);
if (func == nullptr) {
std::cerr << "Unable to find function '" << funcName << "' in LLVM module" << std::endl;
exit(1);
}
// Validate the generated code, checking for consistency.
llvm::raw_os_ostream os(std::cerr);
bool failed = llvm::verifyFunction(*func, &os);
if (failed) {
std::cerr << "Failed to verify function '" << funcName << "' in LLVM module" << std::endl;
exit(1);
}
#if 1
func->dump(); // Dump the function for exposition purposes.
// JIT the function, returning a function pointer.
void *fPtr = executionEngine->getPointerToFunction(func); ///// BAD function pointer!!!!
// Cast it to the right type (takes no arguments, returns a double) so we
// can call it as a native function.
int (*funcPtr)();
*(int **) (&funcPtr) = *(int **) fPtr;
int v = (*funcPtr)();
std::cout << "return: " << v << std::endl;
#else // THIS DOES NOT WORK EITHER:
// JIT the function, returning a function pointer.
uint64_t fPtr = executionEngine->getFunctionAddress(funcName); ///// BAD function pointer!!!!
if (fPtr == 0) {
std::cerr << "Unable to find function '" << funcName << "' in LLVM module" << std::endl;
exit(1);
}
int (*funcPtr)();
*(int **) (&funcPtr) = *(int **) fPtr;
int v = (*funcPtr)();
std::cout << "return: " << v << std::endl;
#endif
}
}
Can anyone help me pin-point the problem?
(I'm running this in linux-ubuntu 15.04)
This assignment is incredibly messed up:
*(int **) (&funcPtr) = *(int **) fPtr;
Not only does it violate strict-aliasing to write an int* and then use it as a function pointer on the next line, but a data pointer is often not large enough to hold an entire code pointer.
The safe approach is either
memcpy(funcPtr, fPtr, sizeof funcPtr);
or
funcPtr = reinterpret_cast<decltype(funcPtr)>(fPtr);