Skip to content

Instantly share code, notes, and snippets.

@peteristhegreat
Created October 11, 2018 19:01
Show Gist options
  • Save peteristhegreat/71b441b25c20530c0f0156a83bc2c54b to your computer and use it in GitHub Desktop.
Save peteristhegreat/71b441b25c20530c0f0156a83bc2c54b to your computer and use it in GitHub Desktop.
Julia dll cpp dynamic loading
// This (static linking to an archive file) doesn't work because we are using a
// different compiler than the one that built julia!
//#include <julia.h>
//#include <iostream>
//using namespace std;
//int main()//int argc, char *argv[])
//{
// cout << "Hello World!" << endl;
// /* required: setup the Julia context */
// jl_init();
// /* run Julia commands */
// jl_eval_string("print(sqrt(2.0))");
// /* strongly recommended: notify Julia that the
// program is about to terminate. this allows
// Julia time to cleanup pending write requests
// and run all finalizers
// */
// jl_atexit_hook(0);
// return 0;
//}
// Heavily based on https://gist.github.com/GunnarFarneback/df2910fa9460cd267b37416f3efea77b
// See also https://docs.julialang.org/en/v0.6.0/manual/embedding/
#include <iostream>
//#define JULIA_ENABLE_THREADING
#include "windows.h"
#include "julia.h"
// DLL resolution also checks in the PATH environment variable
// https://msdn.microsoft.com/en-us/library/7d83bc18.aspx
#define JULIA_DIR "C:\\Users\\USERNAME\\AppData\\Local\\Julia-0.6.4"
#define DLL_CALL_CONVEN __stdcall
#ifdef __cplusplus
extern "C"
{
#endif
// typedef <return type> (DLL_CALL_CONVEN* <func_name>_ptr)(parameter list);
typedef void (DLL_CALL_CONVEN* jl_init_ptr)();
typedef jl_value_t* (DLL_CALL_CONVEN* jl_eval_string_ptr)(const char *);
typedef void (DLL_CALL_CONVEN* jl_atexit_hook_ptr)(int);
#ifdef __cplusplus
}
#endif
using namespace std;
std::string GetLastErrorAsString();
int main()
{
cout << "Hello World!" << endl;
HINSTANCE handle = LoadLibrary(TEXT("libjulia.dll")); // This works if julia.exe is in the path
// HINSTANCE handle = LoadLibrary(TEXT(JULIA_DIR "\\bin\\libjulia.dll"));
if (handle == NULL){
// Apparently it is not loading when executed inside qtcreator_process_stub
// But it will load if executed from Windows Explorer
cerr << "ERROR: Failed to open a handle to the dll" << endl;
cerr << GetLastErrorAsString() << endl;
return 1;
}
cout << "Library Loaded!" << endl;
system("pause");
jl_init_ptr jl_init = (jl_init_ptr)GetProcAddress(handle, "jl_init");
jl_atexit_hook_ptr jl_atexit_hook = (jl_atexit_hook_ptr)GetProcAddress(handle, "jl_atexit_hook");
jl_eval_string_ptr jl_eval_string = (jl_eval_string_ptr)GetProcAddress(handle, "jl_eval_string");
jl_init();
cout << endl << "print(sqrt(2.0))" << endl;
jl_eval_string("print(sqrt(2.0))");
jl_atexit_hook(0);
cout << endl << "Finished running some julia" << endl;
system("pause");
return 0;
}
// https://stackoverflow.com/questions/1387064/how-to-get-the-error-message-from-the-error-code-returned-by-getlasterror
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if(errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment