Why won't lua load my DLL? - c++

I get this error:
FATAL ERROR:
lua_pcall() failed: error loading module 'foo' from file 'C:\Users\Commander\Desktop\Platform\Debug\foo.dll':
The specified procedure could not be found.
I load my DLL file in Lua:
require("foo")
My DLL code, I use Visual Studio Compiler
(It compiles, no errors)
#include "stdafx.h"
#pragma comment( lib, "liblua53.a" )
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <iostream>
using namespace std;
extern "C" {
static int l_bar(lua_State *L)
{
puts("l_bar called.");
return 0;
}
void luaopen_foo(lua_State *L)
{
static const struct luaL_Reg foo[] = {
{ "bar", l_bar },
{ NULL, NULL }
};
luaL_newlib(L, foo);
lua_setglobal(L, "foo");
}
}
Is there anyway around this error, Or is it not possible to load dll files in lua
I found the example c++ code here: https://stackoverflow.com/a/12059441/8767704

Related

Error in making DLL class in Eclipse IDE with g++ compiler

I make a project in Eclipse to export a dll class with g++ compiler. My OS is Ubuntu and the application will run in Ubuntu OS. I created a shared project.
I have compile error as
expected constructor, destructor, or type conversion before ‘(’ token OCR_dll.h /OCR line 19 C/C++ Problem
The error happened at #define DLLCLASS __declspec(dllexport) and how to solve the error. Thank you.
My dll codes header file is
OCR_dll.h
#ifndef OCR_DLL_H_
#define OCR_DLL_H_
#include <stdio.h>
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <tesseract/baseapi.h>
#include <iostream>
#include "Define.h"
#ifdef EXPORT
#define DLLCLASS __declspec(dllexport)
#else
#define DLLCLASS __declspec(dllimport)
#endif
using namespace cv;
#ifdef __cplusplus
extern "C" {
#endif
namespace VIDEOANALYTICS_PLATFORM {
class iOCR{
public:
virtual ~iOCR(){}
virtual int preProcessing(Mat &img) = 0;
virtual int textExtraction(Mat &img) = 0;
};
class OCR : public iOCR{
public:
OCR(){}
~OCR(){ ; }
int preProcessing(Mat &img);
int textExtraction(Mat &img);
private:
};
extern "C"{ DLLCLASS iOCR* __stdcall createOCRObject(); };
}
#ifdef __cplusplus
}
#endif
#endif /* OCR_DLL_H_ */
I got the solution. In Linux environment, dll is called shared library.
The way I create the shared lib is
Headerfile
#ifndef OCR_DLL_H_
#define OCR_DLL_H_
#include <opencv/cv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <tesseract/baseapi.h>
#include <iostream>
#include "Define.h"
using namespace cv;
namespace VIDEOANALYTICS_PLATFORM {
class iOCR{
public:
virtual ~iOCR(){}
virtual int preProcessing(Mat &img) = 0;
virtual int textExtraction(Mat &img) = 0;
};
class OCR : public iOCR{
public:
OCR(){}
~OCR(){ ; }
int preProcessing(Mat &img);
int textExtraction(Mat &img);
private:
};
}
#endif /* OCR_DLL_H_ */
CPP file
#include "OCR_dll.h"
namespace VIDEOANALYTICS_PLATFORM {
extern "C" iOCR* create_object(){
iOCR *p = new OCR();
return p;
}
extern "C" void destroy_object( iOCR* object )
{
delete object;
}
int OCR::preProcessing(Mat &img){
return SUCCESS;
}
int OCR::textExtraction(Mat &img){
return SUCCESS;
}
}
MAKEFILE
g++ -fPIC -shared OCR_dll.cpp -o OCR_dll.so
Then we can create shared lib object for a class.

std::cout/std::cerr seg faults

#include <iostream>
#include <cstring>
#include <dlfcn.h>
#include <fcntl.h>
#include <X11/X.h>
#include <X11/Xlib.h>
void* Module = nullptr;
typedef int (*XNextEventPtr)(Display *display, XEvent *event_return);
XNextEventPtr XNextEventHook = nullptr;
extern "C" int XNextEvent(Display* display, XEvent* event_return)
{
if (event_return)
{
event_return->xany.send_event = false;
}
if (XNextEventHook)
{
return XNextEventHook(display, event_return);
}
return 0;
}
void __attribute__((constructor)) initialize() //DLLMain.
{
char Root[256] = {0};
strcat(Root, "/usr/lib");
#if defined(__x86_64__)
strcat(Root, "/x86_64-linux-gnu");
#else
strcat(Root, "/i386-linux-gnu");
#endif // defined
strcat(Root, "/libX11.so");
Module = dlopen(Root, RTLD_GLOBAL | RTLD_LAZY);
std::cout<<"Loaded"<<std::flush;
XNextEventHook = reinterpret_cast<XNextEventPtr>(dlsym(Module, "XNextEvent")); //some reason RTLD_NEXT didn't find it.
if (XNextEventHook)
{
std::cout<<"Found XNextEvent"<<std::flush;
}
}
void __attribute__((destructor)) deinitialize() //DLLMain.
{
if (Module)
{
dlclose(Module);
Module = nullptr;
}
}
Then I do:
LD_PRELOAD="~/Desktop/MyHook.so" /usr/lib64/firefox
and it will crash. However, it I replace std::cout and std::cerr with printf or perror, it works perfectly!
Is there a reason std::cout would crash the app?
It seems when I load the module using an application written in C++, it loads fine. But if I load the module with an application written in C, it crashes.
Ideas?
But if I load the module with an application written in C, it crashes.
The C application won't have code to call the initialization routines for the C++ library: streams such as std::cout will be uninitialised.
See the FAQ here, specifically:
• You must use your C++ compiler when compiling main() (e.g., for static initialization)

While accessing C++ function from C program, getting error message "Access violation reading location"

I am trying to access C++ function from C program using Visual Studio 2012 IDE. When I am debugging, I am getting the below error in TestCpp.cpp, in Method: helloworld(), in Line: http_client cli( U("http://localhost:55505/api/Notification"));
Unhandled exception at 0x0000000076D23290 (ntdll.dll) in MyTestCLib.exe: 0xC0000005:
Access violation reading location 0x00000621BC90B128.
Please find the code snippet below.
MyTestCLib.c
#include <ctype.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <my_global.h>
#include <mysql.h>
#include <m_ctype.h>
#include "TestCpp.h"
int main()
{
helloWorld();
return 0;
}
TestCpp.h
#ifndef HEADER_FILE
#define HEADER_FILE
#ifdef __cplusplus
extern "C" {
#endif
void helloWorld();
#ifdef __cplusplus
}
#endif
#endif
TestCpp.cpp
// Calling REST API from C++ using C++ REST API SDK
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <iostream>
#include "TestCpp.h"
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
using namespace std;
void helloWorld()
{
http_client cli( U("http://localhost:55505/api/Notification") );
ostringstream_t uri;
uri << U("/PostNotification");
json::value bodyarray = json::value::array();
json::value body = json::value::object();
body[U("TicketNumber")] = json::value::string( U("25868") );
body[U("NotificationMessage")] = json::value::string( U("Test Notification Message") );
bodyarray[0] = body;
http_response response = cli.request( methods::POST, uri.str(), bodyarray.serialize(), U("application/json") ).get();
if ( response.status_code() == status_codes::OK &&
response.headers().content_type() == U("application/json") )
{
json::value json_response = response.extract_json().get();
ucout << json_response.serialize() << endl;
}
else
{
ucout << response.to_string() << endl;
getchar();
}
}
From MyTestCLib.c You call helloWorld declared as C, but complier creates only C++ function version. This call faill because C++ function uses CPU registry and stack different way. There is simple solution. Create C version of function with different name.
TestCpp.h
#ifdef __cplusplus
void helloWorld();
#else
void c_helloWorld();
#endif
TestCpp.cpp
#include "TestCpp.h"
void helloWorld(void)
{
/* cpp code */
}
extern "C" {
void c_helloWorld(void) // C version of helloWorld
{
helloWorld(); // call cpp helloWorld
}
}
Source file with .c extension is complied by C-Compiler. It can't call C++ function. But in .cpp file complied by C++ Compler you can create C function. This "C" function (c_helloWorld) in compiled by C++ compiler and can be called from C-Complier. It can also call C++ function.

getProcAddress - NULL is returned

I have the following code:
//mydll.cpp
#include <Windows.h>
#include <io.h>
#define STDOUT_FILEDESC 1
class MYSTDOUT {
bool shouldClose;
bool isBuffered;
public:
MYSTDOUT(bool buf = true, bool cl = true)
: isBuffered(buf),
shouldClose(cl)
{}
~MYSTDOUT() {
if (shouldClose) {
close(STDOUT_FILEDESC);
}
}
};
__declspec(dllexport) void* mydll_init_stdout()
{
static MYSTDOUT outs;
return &outs;
}
//test_dll.cpp
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <io.h>
typedef void* (__cdecl *MYPROC)(void);
int main(void)
{
int fd;
void *pstdout;
MYPROC init_stdout;
HMODULE handle = LoadLibrary(TEXT("mydll.dll"));
init_stdout = (MYPROC)GetProcAddress(handle,"mydll_init_stdout");//NULL
FreeLibrary((HMODULE) handle);
return 0;
}
I get that init_stdout is NULL.What could be a problem?
handle is OK(Not NULL)
Thank you
That is due to name-mangling.
You need to wrap the exported function in extern "C" as:
extern "C"
{
__declspec(dllexport) void* mydll_init_stdout()
{
static MYSTDOUT outs;
return &outs;
}
}
Have a check in Dependency Walker, or dumpbin /exports and you will see that mydll_init_stdout has been exported with a mangled C++ name. That's why the GetProcAddress call fails.
Use extern "C" to stop mangling.
extern "C"
{
__declspec(dllexport) void* mydll_init_stdout()
{
static MYSTDOUT outs;
return &outs;
}
}

Cpp Pantheios Log Library, Debug Assertion Failed Error

I have a cpp project, a cpp cli project and a c# win forms project.
I use pantheios log library in my cpp native project. When i try to write log, i take this error :
Here is my codes :
Log.hpp
#ifndef INCLUDE_LOG_HPP
#define INCLUDE_LOG_HPP
#define PANTHEIOS_NO_INCLUDE_OS_AND_3PTYLIB_STRING_ACCESS // Faster compilation
/* Pantheios Header Files */
#include <pantheios/pantheios.hpp> // Pantheios C++ main header
#include <pantheios/inserters/args.hpp> // for pantheios::args
#include <pantheios/backends/bec.file.h> // be.file header
#include "Include/utility.hpp"
/* Standard C/C++ Header Files */
#include <exception> // for std::exception
#include <new> // for std::bad_alloc
#include <string> // for std::string
#include <stdlib.h>
#include <sstream>
#define PSTR(x) PANTHEIOS_LITERAL_STRING(x)
namespace Mtx
{
namespace log
{
class MTXMANAGER Logger
{
public:
void WriteLogIn(const std::string & log_text);
Logger();
~Logger();
};
}
}
#endif
Log.cpp
#include "Log.hpp"
namespace Mtx
{
namespace log
{
PANTHEIOS_EXTERN_C const PAN_CHAR_T PANTHEIOS_FE_PROCESS_IDENTITY[] = PANTHEIOS_LITERAL_STRING("mtx");//
Logger::Logger()
{
char path[MAX_PATH];
GetModuleFileName( NULL, path, MAX_PATH );
std::string::size_type pos = std::string( path ).find_last_of( "\\" );
strcpy(path,std::string( path ).substr( 0, pos).c_str());
std::strcat (path,"\\mtx-%D__.log");
/////
pantheios_be_file_setFilePath(PSTR(path), PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_SHARE_ON_WINDOWS, PANTHEIOS_BEID_ALL);
}
Logger::~Logger()
{
}
void Logger::WriteLogIn(const std::string & log_text)
{
pantheios::log_INFORMATIONAL(PSTR(" [1] "),PSTR(log_text));
}
}
}
I take the error at this line :
pantheios::log_INFORMATIONAL(PSTR(" [1] "),PSTR(log_text));
How can i fix this error?
I am afraid I don't have a direct answer for you, but comparing what I have in my solution (which is similar in many aspects with your setup - .NET DLL calling a C++-native DLL, which has Pantheios-logging), here is what I have:
I have a project LOG, which has an InitInstance() and ExitInstance() (and ctors for the CWinApp-derived class - CLogApp)
CLogApp ctor/dtor are empty
The code in InitInstance() and ExitInstance():
BOOL CLogApp::InitInstance()
{
CWinApp::InitInstance();
int panres = pantheios::pantheios_init();
if( panres < 0 )
{
OutputDebugStringA("Could not initialise the Pantheios logging libraries!\n");
util::onBailOut(pantheios::emergency, "Failed to initialise the Pantheios libraries", PANTHEIOS_FE_PROCESS_IDENTITY, /*pantheios::*/pantheios_getInitCodeString(panres));
return FALSE;
}
else
{
pantheios_be_file_setFilePath(CErrorHandler::getLogPath().c_str(), PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BE_FILE_F_TRUNCATE, PANTHEIOS_BEID_LOCAL);
PANTHEIOS_TRACE_NOTICE("STARTING LOGGING");
}
return TRUE;
}
int CLogApp::ExitInstance()
{
PANTHEIOS_TRACE_NOTICE("STOPPING LOGGING");
pantheios_uninit();
return 0;
}
I am not sure if this will help, but this code has been working for me for many years now.