my dll crashes when I call this :
JavaVM *vm;
jint vm_count;
JNI_GetCreatedJavaVMs(&vm, 1, &vm_count);
jvmtiEnv *env = NULL;
vm->GetEnv((void**) &env, JVMTI_VERSION_1_2);
std::cout << env << '\n'; // never print
I don't see any problem so I'm confused
Related
I might be missing something very easy but still i confronted this problem that i couldnt solve. I create a dll with these functions,
extern "C"{
__declspec(dllexport) void some();
__declspec(dllexport) void printer();
}
void printer()
{
printf("printing...\n");
}
i compile it using cmake
cmake .. -G "Visual Studio 15 2017" -A x64 -DBUILD_SHARED_LIBS=TRUE
cmake --build . --config Release
the i load it from my dllloader.cpp
int main() {
HINSTANCE hGetProcIDDLL = LoadLibrary("mydll.dll");
if (hGetProcIDDLL == NULL) {
std::cout << "cannot locate the .dll file" << std::endl;
} else {
std::cout << "it has been called" << std::endl;
}
if(GetProcAddress(hGetProcIDDLL, "printer") == NULL){
}else{
std::cout <<"not null" << std::endl;
}
std::cout << GetLastError() << " err" << std::endl;
getchar();
return 0;
}
So GetLastError returns 0 but nothing is printed, in the original file it is pretty much the same, the function is more that just a printf() call but the function gets loaded, how do we run it ? I know i might be missing something, just function does not execute. Any help is appreciated
typedef void(*my_dll_print)(); // function pointer to print method of dll
int main()
{
HINSTANCE hGetProcIDDLL = LoadLibrary("mydll.dll");
if (hGetProcIDDLL == nullptr)
std::cout << "cannot locate the .dll file" << std::endl;
else
std::cout << "it has been called" << std::endl;
my_dll_print print_method = reinterpret_cast<my_dll_print>(GetProcAddress(hGetProcIDDLL, "printer")); // Extract method address and create pointer
if (print_method == nullptr)
std::cout << "is null" << std::endl;
else
print_method(); // Call dll method
std::cout << GetLastError() << " err" << std::endl;
getchar();
return 0;
}
Try to use nullptr instead NULL to check pointer.
GetProcAdrress retrieves the address of an exported function or variable from the specified dynamic-link library! and makes no function call. You must first assign to function pointer then make call to pointed function!
I'm creating a C++ wrapper for an existing jarfile. In this case, I'm doing this with the Spigot Minecraft server jarfile.
When I execute the application, I have the issue where the input and the output of the application is dominated by the Java application. This means that when the java application terminates successfully, so does the C++ application, which indicates that the file descriptor for stdin is getting closed.
I've looked through a number of existing stackoverflow posts, and the closest that I've seen to achieve this, was making use of a forked process, and then piping the file descriptors using pipe() and dup():
C/Linux - having trouble with redirecting stdin and stout
I'm currently rebuilding the code to make it more portable, and allow me to add additional functionality to the C++ code, but the following code is what I've used to get started, and is what I'll be using to test this.
#include <jni.h>
#include <iostream>
using namespace std;
int main () {
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = "-Djava.class.path=/path/to/spigot.jar";
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
jint instance = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
delete options;
if (instance != JNI_OK) {
cin.get();
exit(EXIT_FAILURE);
}
cout << "JVM Version: ";
jint ver = env->GetVersion();
cout << ((ver>>16)&0x0f) << "." << (ver&0x0f) << endl;
jclass cls = env->FindClass("org/bukkit/craftbukkit/Main");
if (cls == nullptr) {
cout << "Error starting minecraft" << endl;
} else {
jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
if (mid == nullptr) {
cout << "Error: main not found" << endl;
} else {
jobjectArray arr = env->NewObjectArray(1,
env->FindClass("java/lang/String"),
env->NewStringUTF(""));
env->CallStaticVoidMethod(cls, mid, arr);
cout << "Started" << endl;
cout << endl;
}
}
cin.get();
jvm->DestroyJavaVM();
return 0;
}
Ideally, I would like to have the input and output of the java application run on a different set of file descriptors for stdin, stdout, and stderr, without forking it.
Is there a way to indicate to the JVM, using the JNI library within c++ to achieve this goal?
You can just call System.setIn and System.setOut.
Alternatively, just call the native implementations setIn0 and setOut0 directly or copy their implementation.
The latter would look something like:
// Make a FileOutputStream
jclass os_cla = env->FindClass("java/io/FileOutputStream");
jmethodID os_init = env->GetMethodID(os_cla, "<init>", "(Ljava/lang/String;)V");
jobject os = env->NewObject(os_cla, os_init, env->NewStringUTF("output.txt"));
// Make a PrintStream
jclass ps_cla = env->FindClass("java/io/PrintStream");
jmethodID ps_init = env->GetMethodID(ps_cla, "<init>", "(Ljava/io/PrintStream;)V");
jobject ps = env->NewObject(ps_cla, ps_init, os);
// Reassign System.out
jclass system_cla = env->FindClass("java/lang/System");
jfieldID fid = env->GetStaticFieldID(system_cla, "out", "Ljava/io/PrintStream;");
env->SetStaticObjectField(system_cla, fid, ps);
I would like to know how to check if a preloaded module exists or not in Lua using C++.
My Code :
#include "lua.hpp"
bool isModuleAvailable(lua_State *L, std::string name)
{
//what should be here?
return false;
}
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_settop(L, 0);
luaL_dostring(L, "package.preload['A'] = function()\n"
"local a = {}\n"
"return a\n"
"end\n");
luaL_dostring(L, "package.preload['B'] = function()\n"
"local b = {}\n"
"return b\n"
"end\n");
if (isModuleAvailable(L, "A"))
std::cout << "Module Available" << '\n';
else
std::cout << "Module Not Available" << '\n';
if (isModuleAvailable(L, "B"))
std::cout << "Module Available" << '\n';
else
std::cout << "Module Not Available" << '\n';
if (isModuleAvailable(L, "C"))
std::cout << "Module Available" << '\n';
else
std::cout << "Module Not Available" << '\n';
lua_close(L);
}
The Result I get :
Module Not Available
Module Not Available
Module Not Available
The Result I want :
Module Available
Module Available
Module Not Available
How can I create isModuleAvailable() function so my code can work as expected?
Just check whether the field package.preload[name] is nil. I also renamed the function to isModulePreloaded because that's what is checks.
bool isModulePreloaded(lua_State *L, std::string const &name) {
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
lua_getfield(L, -1, name.c_str());
bool is_preloaded = !lua_isnil(L, -1);
lua_pop(L, 3);
return is_preloaded;
}
I'm creating a Qt WebEngine application for Windows that display a webpage and uses printer to print out whatever is displayed. I'm trying to get an error state out of my Custom vkp80III ticket printer using windows' winspool library and this example https://support.microsoft.com/en-us/kb/160129
App has this print call. (printerState is useless, it seems to be always idle but anyways):
void printReceipt() {
if (mDefaultPrinter->printerState() == QPrinter::Error) {
this->printCallback(false);
}
else {
this->print(mDefaultPrinter, [=](bool success) { this->printCallback(success); });
}
}
And then comes the problem, callback after print succesfully started:
void printCallback(bool success){
DWORD size;
bool result = GetDefaultPrinter (NULL, &size);
qDebug() << "LEN: " << size;
LPWSTR pname = (LPWSTR)malloc(size+1);
result = GetDefaultPrinter(pname, &size);
if(!result){
qDebug() << "GetDefaultPrinter err: " << GetLastError();
}
else {
pname[size] = 0;
qDebug() << "PRINTER NAME: " << &pname << ", LEN: " << size;
}
QString name = mDefaultPrinter->printerName();
//These give more or less odd results
//wchar_t* w_str = const_cast<wchar_t*>(name.toStdWString().c_str());
//LPWSTR w_str = (LPWSTR)name.utf16();
/*wchar_t* w_str = (wchar_t*) malloc (sizeof(wchar_t)*name.length()+1);
int len = name.toWCharArray(w_str);
w_str[len]=0;*/
//OpenPrinter example uses LPHANDLE but that didn't work
HANDLE hPrinter = NULL;
PRINTER_DEFAULTS pd;
ZeroMemory(&pd, sizeof(pd));
pd.DesiredAccess = PRINTER_ALL_ACCESS;
qDebug() << "TRYING GET PRINTER: " << name;
if(OpenPrinter(pname, &hPrinter, &pd)) {
qDebug() << "GOT PRINTER ERR STATE: " << IsPrinterError(&hPrinter);
}
free(pname);
emit printReceiptComplete(success);
}
I put couple of debug logs inside MSDN example and it shows that when code tries to GetPrinter(hPrinter) it returns INVALID_HANDLE_ERROR. So I never get to point of getting the printer's errors. First I thought it was the wrong printer name, that's why there are different lines of code getting it / converting it to LPWSTR.
So what works:
-I get default printer's name "CUSTOM VKP80III" so it IS there
-OpenPrinter(&handle) returns true and I get the handle
Problem
-GetPrinter(handle) returns false and GetLastError() is invalid handle, why?
Oh so much facepalming right now. This:
IsPrinterError(&hPrinter);
should be this:
IsPrinterError(hPrinter);
I wrote next program:
#include <iostream>
#include <dlfcn.h>
int main(int argc, char** argv)
{
typedef void* (*fptr)();
fptr func;
void *handle = dlopen(0, RTLD_NOW);
std::cout << dlerror() << std::endl;
*(void **)(&func) = dlsym(handle, "__libc_start_main");
std::cout << dlerror() << std::endl;
std::cout << handle << " " << func << "\n";
dlclose(handle);
return 0;
}
and try to compile in next way:
g++ -rdynamic main.cpp -ldl -o test
When I run this program I don’t see any message. Why?
Thank U for attention.
Your process is faulting because dlerror() is only valid to call in an error condition, which you never validated actually happened prior to invocation.
From the Linux docs:
The function dlerror() returns a human readable string describing the
most recent error that occurred from dlopen(), dlsym() or dlclose()
since the last call to dlerror(). It returns NULL if no errors have
occurred since initialization or since it was last called.
In other words, your dlopen succeeded, so NULL is returned from dlerror(). That NULL is then sent as a char * to std::cout, and kerboom.
Bottom line: check your error conditions before invoking dlerror(). Try this instead:
#include <iostream>
#include <dlfcn.h>
int main(int argc, char** argv)
{
typedef void* (*fptr)();
fptr func;
void *handle = dlopen(0, RTLD_NOW);
if (handle == nullptr)
{
std::cout << dlerror() << std::endl;
exit(EXIT_FAILURE);
}
func = (fptr)dlsym(handle, "__libc_start_main");
if (!func)
{
std::cout << dlerror() << std::endl;
exit(EXIT_FAILURE);
}
std::cout << handle << " " << func << "\n";
dlclose(handle);
return 0;
}
This is (likely) undefined behavior:
std::cout << dlerror() << std::endl;
...unless dlerror is actually non-null (which it probably isn't). It should be:
char* error = dlerror();
if (error != 0)
std::cout << error << std::endl;
...or:
void *handle = dlopen(0, RTLD_NOW);
if (handle == 0)
std::cout << dlerror() << std::endl;
Also, you probably should abort if dlerror is non-null (or handle is null), because calling dlsym on an null handle is also undefined behavior.
See Why does std::cout output disappear completely after NULL is sent to it.