call matlab dll from c++: fail to initialize the library - c++

I try to use Demo code for detecting and matching SIFT features of David Lowe (lowe#cs.ubc.ca)
in my code. So I compile the (.m)file in Matlab to generate DLL. Here is the command code in Matlab:
mcc -B csharedlib:SiftMatch match.m sift.m -v
However, when I use the DLL in my C++ code( under VS2010), there is a problem:
SiftMatchInitialize();
This function returned false. I could not initialize the library.
and debug showed that:
bool MW_CALL_CONV SiftMatchInitializeWithHandlers(
mclOutputHandlerFcn error_handler,
mclOutputHandlerFcn print_handler)
{
int bResult = 0;
if (_mcr_inst != NULL)
return true;
if (!mclmcrInitialize())
return false;
if (!GetModuleFileName(GetModuleHandle("SiftMatch"), path_to_dll, _MAX_PATH))
return false;
{
mclCtfStream ctfStream =
mclGetEmbeddedCtfStream(path_to_dll);
if (ctfStream) {
bResult = mclInitializeComponentInstanceEmbedded( &_mcr_inst,
error_handler,
print_handler,
ctfStream);
mclDestroyStream(ctfStream);
} else {
bResult = 0;
}
}
if (!bResult)
return false;
return true;
}
In this function ctfStream is NULL and bResult equals 0.
So, what's the problem?

Do not include the .c/.cpp files generated by MATLAB Compiler into your project. Only the header file and .lib file is needed.

Related

How to get the directory of the current DLL

I will build c-shared in golang -o config.dll.
Let's say the directory is c:\test\config.dll
In mail.dll, I'm going to open a configuration file.
This file is in the directory of config.dll.
c:\test\config.json
I'm calling it in c++ c:\test\c++.dll.
In c++ I use
{ // NB: XP+ solution!
HMODULE hModule = NULL;
GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)GetCurrentModule,
&hModule);
return hModule;
}
WCHAR path3[MAX_PATH + 1] = { 0 };
HMODULE hm = GetCurrentModule();
::GetModuleFileName(hm, path3, MAX_PATH);
PathRemoveFileSpec(path3);
// path3 c:\test\c++.dll
What is the equivalent of this in Go?
I try to use
os.Getwd()
runtime.Caller(1)
os.Args[0]
os.Executable()
I want to get directory c:\test\
You can use cgo to call the same function in whatever library it exists.

Properly setting up tinycc with visual studio 2019, library libtcc1-32.a not found

I'm using tcclib to compile and run C code on the fly in my C++ project.
I'm using the binaries provided here https://bellard.org/tcc/
I then open a vs2019 developer prompt and run both those command
lib /def:libtcc\libtcc.def /out:libtcc.lib
cl /MD examples/libtcc_test.c -I libtcc libtcc.lib
My code builds fine, I'm using this code. This code is similar to the one found in the tcclib example, which is this one : https://repo.or.cz/tinycc.git/blob/HEAD:/tests/libtcc_test.c (this is another repo, but it's the same code.
The code I run is this one. This is inside an extern "C" {}.
int tcc_stuff(int argc, const char** argv) {
TCCState* s;
int i;
int (*func)(int);
s = tcc_new();
if (!s) {
fprintf(stderr, "Could not create tcc state\n");
exit(1);
}
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
for (i = 1; i < argc; ++i) {
const char* a = argv[i];
if (a[0] == '-') {
if (a[1] == 'B')
tcc_set_lib_path(s, a + 2);
else if (a[1] == 'I')
tcc_add_include_path(s, a + 2);
else if (a[1] == 'L')
tcc_add_library_path(s, a + 2);
}
}
/* MUST BE CALLED before any compilation */
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
{
const char* other_file = ReadFile2(argv[1]);
if (other_file == NULL)
{
printf("invalid filename %s\n", argv[1]);
return 1;
}
if (tcc_compile_string(s, other_file) == -1)
return 1;
}
/* as a test, we add symbols that the compiled program can use.
You may also open a dll with tcc_add_dll() and use symbols from that */
tcc_add_symbol(s, "add", add);
tcc_add_symbol(s, "hello", hello);
/* relocate the code */
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
return 1;
/* get entry symbol */
func = (int(*)(int))tcc_get_symbol(s, "foo");
if (!func)
return 1;
/* run the code */
msg(func(32));
//msg(func2(4));
/* delete the state */
tcc_delete(s);
return 0;
}
When running my code, TCC had the error
tcc: error: library 'libtcc1-32.a' not found
I fixed it by placing this file in the lib/ directory next to my .exe
I also copied the include/ folder to include stdio.h etc.
My question is: why does it need this file in a lib/ folder, instead of the provided tcclib.dll file? Is it possible to "ship" certain headers like stdio.h?
The question has no answer but 360 views, so I thought I'd reply.
The library doesn't necessarily need to be in that folder. To quote the author's command line docs, which still apply to the library,
-Ldir
Specify an additional static library path for the -l option. The default library paths are /usr/local/lib, /usr/lib and /lib.
I inferred your program to be a modified main() of libtcc_test.c & fixed it to the point of functioning. Then I used VS2022 to retrace your steps, put the .a files into the same folder as my new tests_libtcc_test.exe, then I ran this:
tests_libtcc_test c:/lang/tcc/examples/fib.c -Ic:/lang/tcc/include -L.
The library issue appears if I don't -L anything, and disappears if I include at least the ".".
And of course, you can drop the include folder into your redistributable and include it by default right from the code.
Because the tcc DLL is just another interface to the same compiler, it needs the same things tcc.exe would to build an executable; in this case, it needs the same libraries.

On Windows QDir::mkpath and QFile::rename report success despite failing

I'm trying to add auto-update functionality to the app I'm working on. My solution works well on Linux, but I'm running into weird problems on Windows.
After unpacking the update package I'm trying to move it to the destination directory using the following function:
inline void recursiveMoveOrCopy(QDir source, QDir dest, bool move)
{
auto files = source.entryInfoList(QDir::Files);
auto dirs = source.entryInfoList(QDir::Dirs|QDir::NoDotAndDotDot);
// move / copy files
bool success = QDir{}.mkpath(dest.path());
if (!success){
throw std::runtime_error(qs("Could not crate directory %1")
.arg(dest.path()).toStdString());
}
qDebug()<<"created directory"<<dest.path();
dumpvar(QDir{}.exists(dest.path()));
for (auto& file: files){
QString sourcePath = file.filePath();
QString fileName = file.fileName();
QString destPath = dest.filePath(fileName);
QString backupPath = destPath + "_bck";
bool success;
bool backup = false;
if (QFile::exists(destPath))
backup = QFile::rename(destPath, backupPath);
ON_EXIT{
if (backup) {
QFile::remove(destPath);
QFile::rename(backupPath, destPath);
}
};
if (move) success = QFile::rename(sourcePath, destPath);
else success = QFile::copy(sourcePath, destPath);
qDebug()<<qs("move from %1 to %2 was %3").arg(sourcePath, destPath, success?"successful":"not sucessful");
if (success && backup){
QFile::remove(backupPath);
backup = false;
}
if (!success){
throw std::runtime_error(qs("Failed to %1 file %2 to %3")
.arg(move?"move":"copy")
.arg(sourcePath)
.arg(destPath)
.toStdString());
}
}
// recursively move/copy dirs
for (auto &dir: dirs) recursiveMoveOrCopy(dir.filePath(), dest.filePath(dir.fileName()), move);
}
I made a small package for testing with just 2 files and 1 directory:
$ tree .
.
├── katalog
│   └── plik
└── plik2
When I try to install this "update" the following is written to debug output by the move function:
"moving C:/Users/piotrek/AppData/Local/Temp/dres-update-image to C:/Program Files (x86)/DRES"
created directory "C:/Program Files (x86)/DRES"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/plik2 to C:/Program Files (x86)/DRES/plik2 was successful"
created directory "C:/Program Files (x86)/DRES/katalog"
QDir{}.exists(dest.path()) = true
"move from C:/Users/piotrek/AppData/Local/Temp/dres-update-image/katalog/plik to C:/Program Files (x86)/DRES/katalog/plik was successful"
As in: every single operation succeeded. But when I look into the target directory, the directory katalog doesn't exist (the file plik2 does however).
Note that even though the directory does NOT exist, QDir::exists reports that it does.
It's not a permission problem, when I was testing this I modified C:/Program Files (x86)/DRES to give Everyone full access.
Please tell me I'm not crazy. What the hell is going on here?
EDIT: Thanks to Rudolfs' suggestion to use Process Monitor I discovered the the files are actually being written to C:\Users\piotrek\AppData\Local\VirtualStore\Program Files (x86)\DRES. What exactly is going on here and how do I fix this?
Ok, I figured it out.
I had to use the following code to disable VirtualStore virtualization for the whole app:
#ifdef Q_OS_WIN32
#include <windows.h>
QString getWinError()
{
DWORD dw = GetLastError();
LPWSTR lpMsgBuf = NULL;
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR) &lpMsgBuf,
0, NULL );
QString str = QString::fromWCharArray(lpMsgBuf);
LocalFree(lpMsgBuf);
return str;
}
bool disableVirtualStore()
{
HANDLE token;
DWORD tokenInformation = 0;
if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)){
qWarning()<<getWinError();
return FALSE;
}
ON_EXIT{
CloseHandle(token);
};
if(!SetTokenInformation(token, TokenVirtualizationEnabled,
&tokenInformation, sizeof(tokenInformation))) {
qWarning()<<getWinError();
return FALSE;
}
return TRUE;
}
#endif
Now I can normally write to all folders that I have write access to, and since Windows no longer lies to me about having write access, I can start an elevated helper app to move files to folders where I don't have write permission.

Writing PNG file from pixel data using libpng

I am trying to write PNG file (saving an image in png format) from pixel data read by glReadPixels in openGL using following piece of code (copied from here):
bool writePNGFileFromBuffer(const char *filename, unsigned char *pixels, int w, int h)
{
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);//8
if (!png)
return false;
png_infop info = png_create_info_struct(png);//7
if (!info) {
png_destroy_write_struct(&png, &info);//
return false;
}
FILE *fp = fopen(filename, "wb");
if (!fp) {
png_destroy_write_struct(&png, &info);//
return false;
}
png_init_io(png, fp);//9
png_set_IHDR(png, info, w, h, 8 /* depth */, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);//10
png_colorp palette = (png_colorp)png_malloc(png, PNG_MAX_PALETTE_LENGTH * sizeof(png_color));//4
if (!palette) {
fclose(fp);
png_destroy_write_struct(&png, &info);//
return false;
}
png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH);//12
png_write_info(png, info);//1
png_set_packing(png);//5
png_bytepp rows = (png_bytepp)png_malloc(png, h * sizeof(png_bytep));//
for (int i = 0; i < h; ++i)
rows[i] = (png_bytep)(pixels + (h - i) * w * 3);
png_write_image(png, rows);//2
png_write_end(png, info);//6
png_free(png, palette);//11
png_destroy_write_struct(&png, &info);//3
fclose(fp);
delete[] rows;
return true;
}
I linked the libpng and zlib libraries in the additional dependencies. But when I compile the code it gives following error:
Error 77 error LNK2001: unresolved external symbol png_write_info
It gives this error at about 12 instances marked in the code snippet above. I am clear that it is not able to find the definitions of the functions but I do not know why?
Any help would be appreciated. Thanks
Edit: I looked into the header file "png.h" and it contains declarations for all the functions. Functions are defined in "pngwrite.c" and I think it should take it from the linked library.
Edit2: After hitting around for couple of days, I found that when I change the output type of my project (in which I am using libpng.lib) to Static Lib (.lib), everything works and the code compiles well but with .dll output it throws the above specified error.
And my problem is, I have to use .dll output because that I use in another huge project which I cant change to accept .lib.
Any help on this?
You may be missing "pnglibconf.h" which you must copy from
scripts/pnglibconf.h.prebuilt to pnglibconf.h in your source directory.

C++ GetBinaryType Failing

I am using GetBinaryType to check if an executable is 32 or 64bit. I am testing against a 64bit file and it keeps failing. I believe this is due to the way I am comparing the DWORD result?
I am using Visual Studio 2010 C++:
DWORD dwBinaryType;
if (GetBinaryType(ChildFile(), &dwBinaryType) == 6)
{
MessageBox(NULL, L"64bit Detected...", L"Debug: GetBinaryType", MB_OK); // DEBUG
}
else
{
MessageBox(NULL, L"Probably 32bit...", L"Debug: GetBinaryType", MB_OK); // DEBUG
}
Any advice would be great thanks.
According to MSDN for GetBinaryType:
Return value
If the file is executable, the return value is nonzero. The function sets the variable pointed to by lpBinaryType to indicate the file's executable type.
Changing your above code to this should do the trick:
if (GetBinaryType(ChildFile(), &dwBinaryType)
&& dwBinaryType == SCS_64BIT_BINARY)
{
// ...
}