I need to call a subproject from a main project and implemented two ways of doing that.
It turns out, that the second way is a factor 4 slower than the first.
Can anybody explain this to me?
The subproject looks like this:
#include "fancyProject.h"
int main (int argc, char *argv[])
{
std::string controlFile = argv[1];
return runFancyProject(controlFile);
}
First way: Call the binary of the subproject in the main project via the system() function:
std::string command = "fancyProject controlFile.dat";
int result = system(command.c_str());
Second way: Create a library from the subproject, link this library with the main project and call the specific function:
#include "fancyProject.h"
std::string controlFile = "controlFile.dat";
int result = runFancyProject(controlFile);
In the meantime, I created a minimal example. However, it behaves as expected: The system() function is slower than the call of the linked function. Thus, the error has to be somewhere else in the project. Nevertheless thank you very much for your time, especially to dsboger. I will do further investigations in this direction.
Related
I have some code that is compiled as a shared library and used with a universal driver, which can be used with other shared libraries that are specific to a particular application.
My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.
For example, let's say I have 3 files, the first is driver.cpp, the universal driver:
#include "interface.h"
#include <stdio.h>
int main(int argc, char *argv[]) {
//perform a function from the shared library
std::cout << foobar() << std::endl;
}
The second is sharedlibrary.cpp, the specific implementation for one case of many:
#include "interface.h"
char* foobar() {
return x;
}
Where x is some indicator that this function is defined in sharedlibrary.cpp, or that this function is linked from sharedlibrary.so, or the current stack frame is using the specific binary rather than just being included in driver.cpp.
The last file is interface.h, which provides the interface to the library via extern "C"
extern "C" {
char foobar();
}
I would like to reiterate, for clarity, that I am looking for some indication that this function is being linked from sharedlibrary.so. Many solutions looking for runtime filenames give the executable name using either argv[0] or readlink(), but I have no control over the actual naming of driver.cpp or its executable name. Rather, I can distribute sharedlibrary.so, and would like to be able to use its name from within itself, if possible.
If it helps, I know that a microsoft-specific solution could be to use AfxGetApp()->m_pszAppName to obtain the DLL name. However, I am looking for a linux solution that does not necessarily need to be portable.
EDIT: I do not know or control the names of driver.cpp, sharedlibrary.cpp, or sharedlibrary.h at compile time. I wish to discover the name of sharedlibrary.cpp at run time.
The updated sharedlibrary.cpp with x replaced with the solution looks like this
#include "interface.h"
#include <dlfcn.h>
void func() {
//Some function that is defined in sharedlibrary.cpp
}
char* foobar() {
Dl_info DlInfo;
if(!dladdr((void*)func, &DlInfo)) {
return "default_name";
}
return DlInfo.dli_fname;
}
Obtaining filename at runtime for a shared library c++
My question pertains to obtaining some sort of indicator of the name of the binary containing a code that lives in that shared library.
You can use int dladdr(void *addr, Dl_info *info. It fills a following structure for you:
typedef struct {
const char *dli_fname; /* Pathname of shared object that contains address */
void *dli_fbase;
const char *dli_sname;
void *dli_saddr;
} Dl_info;
You can pass the address of a function exported by the shared library as the argument addr. Or within such function, you could use the instruction pointer value of the current stack frame - if you know how to obtain it.
I believe you must link with the libdl library.
You can use the buildsystem to generate the dynamic library name for linking and preprocess that inside of a header with a function that return a defined macro, in cmake you can see how to do that here.
Then you use the configured-file to return the defined value in a function that's exported from within the dll.
#include "library_name_macro.h"
auto __dllexport libraryName() -> std::string { return LIBRARY_NAME_MACRO; }
I hope, I have understood your question correctly. I hope my answer helps. You know the shared library name, you link that shared library to your program, Later in run time you want to figure out whether a particular function is present in library or not and this logic should be part of shared library itself.
Let's take an example that you have shared library called librandom.so, You have linked this library to your application. You can implement the following function in a librandom.so library, You can pass function name which you want to check whether it is present or not. I have not tested this code, there may be errors. The idea I am proposing is library loads itself again to check whether the function is present when this function is called. May not be ideal method but should serve your purpose.
int isFuncPresent(char funcName[])
{
int isFuncFound = 1;
void *lib_handle;
int x;
char *error;
lib_handle = dlopen("librandom.so", RTLD_LAZY);
if (!lib_handle)
{
fprintf(stderr, "%s\n", dlerror());
isFuncFound = 0;
}
fn = dlsym(lib_handle, funcName);
if ((error = dlerror()) != NULL)
{
fprintf(stderr, "%s\n", error);
isFuncFound = 0;
}
dlclose(lib_handle);
return isFuncFound;
}
I'm just learning c++. I have a main.cpp unit which has a lot of stuff in it already, and I just want to build a quick little testMain.cpp unit that will test a couple of things.
Basically I want to trick the compiler (xCode) into ignoring the real main function for a minute. I could
Rename the main() function inside main.cpp to mmain() temporarily.
Remove the reference to main.cpp in my project temporarily.
Comment out the main() method in main.cpp temporarily.
All these seem pretty clunky. There has to be an easier way. I suspect this is a common thing people do. How do you do it?
Another solution would be to separate the code into multiple files, have most of the logic in one file, have the real main in another and the test main in a third, you compile and link either the first and second or first and third files but never all three together.
Your option 2 is the most common strategie, and from my understanding also the cleanest.
After all, your test application will most likely not share the same command line interface, and that is usually about the only thing which should (of at all) be located in the main function or file.
If your main.cpp contains significantly more than just the entry point, you should immediately start thinking about how to distribute that logic into the modules you already have.
Use a macro.
Option 1: Use a macro to include/exclude entire files:
main.cpp:
#ifdef USE_REAL_MAIN
int main(int argc, char* argv[]) {
...
}
#endif
testMain.cpp
#ifdef USE_TEST_MAIN
int main(int argc, char* argv[]) {
...
}
#ENDIF
build file:
gcc -DUSE_REAL_MAIN
gcc -DUSE_TEST_MAIN
Option 2: Use a command-line macro to rename main:
main.cpp:
int realMain(int argc, char* argv[]) {
...
}
testMain.cpp
int testMain(int argc, char* argv[]) {
...
}
build file:
gcc -DrealMain=main
gcc -DtestMain=main
Note this is probably the least attractive option because it breaks the convention of macros having UPPER_CASE names and means the real entrypoint of your program is non-obvious to someone who hasn't seen the build script. It also means the program simply won't compile (as there's no main function) without your custom build script either.
Option 3: Have a new common main with the #ifdef directives instead:
main.cpp
#include "realMain.h"
#include "testMain.h"
int main(int argc, char* argv[]) {
#ifdef USE_TEST_MAIN
return testMain( argc, argv );
#else
return realMain( argc, argv );
#endif
}
build file:
gcc -DUSE_REAL_MAIN
gcc -DUSE_TEST_MAIN
I think this is my preferred option because it's almost self-documenting and makes it clear to another programmer how to get it to work without needing your custom build script.
I am trying out CLion as new IDE and I have this odd problem with debugging. I am trying to step into function cropImage (not method) but all I can get when stepping into is to get to constructor of CRect.
int main ( void )
{
cropImage( "./sample/input_00.raw", "./output_00.raw", CRect(1,2,3,4), ENDIAN_LITTLE);
return 0;
}
Also, when I try to put breakpoint inside function cropImage() it just get ignored. What am I doing wrong? I think this is pretty much basic function of debugger to step into function, not only methods...
I am using CLion on Linux with GDB and g++.
EDIT:
Just to clarify the code and issue here is how the file main.cpp looks
bool cropImage ( const char * srcFileName,
const char * dstFileName,
const CRect & rc,
int byteOrder )
{
// Open streams, create objects, do stuff
}
int main ( void )
{
cropImage( "./sample/input_00.raw", "./output_00.raw", CRect(1,2,3,4), ENDIAN_LITTLE);
return 0;
}
Everything works from CLI ( using gdb on binary created from CLion ), it just that inside of IDE it ignores any breakpoint inside cropImage() function.
So I find this workaround. Ref: https://intellij-support.jetbrains.com/hc/en-us/community/posts/206606815-Integrated-GDB-and-a-frame-not-available-error
Seems like it's issue on ArchLinux. Even though CLion detects gdb automatically without problems, frames doesn't exist and manually specifying path to gdb (/usr/bin/gdb) fixed this.
int main(int argc, char* argv[])
{
std::string s1;
pcrecpp::RE re("(.*)");
re.PartialMatch("This is a test progream", &s1);
return 0;
}
I want to store the match result to s1, but when I am running the program, an error occurs:
This is the stack trace information:
pcrecpp version: 8.36
compiler: vs2005
I find a better way to solve this problem. As pcrecpp.dll will malloc memory, and this will cause faults on windows. So, first, I build the pcre.dll; then add pcrecpp files to my project, thus solve the memory malloc problem.
Use pcre.8.36 as an example:
1. Use pcre files to generate pcre.dll:
pcre_byte_order.c
pcre_chartables.c
pcre_compile.c
pcre_config.c
pcre_dfa_exec.c
pcre_exec.c
pcre_fullinfo.c
pcre_get.c
pcre_globals.c
pcre_jit_compile.c
pcre_maketables.c
pcre_newline.c
pcre_ord2utf8.c
pcre_refcount.c
pcre_string_utils.c
pcre_study.c
pcre_tables.c
pcre_ucd.c
pcre_valid_utf8.c
pcre_version.c
pcre_xclass.c
pcre.h
pcre_internal.h
ucp.h
config.h
Add
pcre_scanner.cpp
pcre_stringpiece.cpp
pcrecpp.cpp
pcre_scanner.h
pcre_stringpiece.h
pcrecpparg.h
to my project, OK!
I want to replace the calls to system() function made by my program using LD_PRELOAD.
So I created the following wrapper functions in a shared library for testing.
// syshook.c
int system(const char * command)
{
printf("system() called for %s ************************************\n", command);
return 55;
}
char * getenv (const char* name)
{
printf("my getenv() *********************");
return 0;
}
And compiled and linked to a shared object libsyshook.so with gcc.
gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libsyshook.so -o libsyshook.so.1.0
ln -s libsyshook.so libsyshook.so.1.0
However, when I run the program with with LD_PRELOAD as shown below, my wrapper function for system() is not called, but the wrapper for getenv() called.
LD_PRELOAD="libsyshook.so" myprog
When I attach the debugger, I can see that system() call, calls the implementation in libpthread.so. So why is redirecting system() not working. I don't think there is any limitation on that ??
Edit:
My test program compiled to myprog above looks like this. Comments indicate my observations.
void TestClass::testMethod()
{
string cmdLine = "date";
if (!mainWin) cmdLine = "time";
int retFromSys = system(cmdLine.c_str()); // goes into libpthread when stepped in.
cout << "return from system " << retFromSys << endl; // prints 0, not 55
getenv("DEBUG_SYS"); // Wrapper function called for this. Prints "my getenv ****** ..."
The most usual case of bad linking with LD_PRELOAD is when GCC replace your function by another one, when he think it can make your code faster to execute.
For instance, if GCC read this line in your code :
printf("%d", strlen("toto"));
It will replace with this line before compiling it :
puts("4");
Because it knows the printf and strlen functions, and think the output would be the same with puts function.
In this example, if you made your own printf or strlen function in a library loaded with LD_PRELOAD, your function won't be called after compilation, because GCC would have replaced function calls.
I think your problem is for the same reason. system is a very heavy function, and GCC may replaced your function call by another. For instance, if you tried :
system("ls");
GCC might replaced your line by :
execlp("ls", "ls");
That would do the same, but in less heavy. It couldn't know that you wanted to use your own system function. Try to disassemble your code to check if this is the problem.
As solution, I suggest you to try to call system with a more "random" parameter, to make GCC think it should not try to replace it. Maybe something like :
int main(int argc, char** argv)
{
char* line = NULL;
// Useless condition to make GCC think the parameter is variable
if (argc == 1)
line = "ls";
return (system(line));
}