How to link properly Dcmtk with Qt for Linux? - linux

My goal is open Dicom files and convert thes into cv::Mat to process them with Opencv.
I have compiled dcmtk 3.6.3 on ubuntu 18.4.1 and tried to link it with Qt 5.11.1 with Qt Creator 4.6.2 but failed to do so.
# pro file
QT += core
QT -= gui
TARGET = DcmtkTesting
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
DCMTK_PREFIX = "/home/ismail/dcmtk363"
DCMTK_LIBS_PREFIX=$$DCMTK_PREFIX"/lib"
DCMTK_INCLUDE=$$DCMTK_PREFIX"/include"
INCLUDEPATH+=$$DCMTK_INCLUDE
LIBS += -L$$DCMTK_LIBS_PREFIX
SOURCES += main.cpp
and for the main:
#include
#include "dcmtk/config/osconfig.h"
#include "dcmtk/dcmdata/dctk.h"
#include <dcmtk/dcmimgle/dcmimage.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
DicomImage *image = new DicomImage("test.dcm");
if (image != NULL)
{
if (image->getStatus() == EIS_Normal)
{
if (image->isMonochrome())
{
image->setMinMaxWindow();
Uint8 *pixelData = (Uint8 *)(image->getOutputData(8 /* bits*/));
if (pixelData != NULL)
{
/* do something useful with the pixel data */
}
}
} else
cout << "Error: cannot load DICOM image (" << DicomImage::getString(image->getStatus()) << ")" << endl;
}
delete image;
return a.exec();
}
and I got this errors:

The error indicates that the linker could not find the symbols (methods) provided by the library. In your .pro file, you pointed the linker to a directory where your library is located, but you forgot to specify which library should be linked.
So you have to modify the line LIBS +=... accordingly, e.g.:
LIBS += -L$$DCMTK_LIBS_PREFIX -ldcmtk
Since I don't know the actual name of the library, I use dcmtk in my example. You may have to adopt it to fit your build environment. Just make sure that you have the -l (lower case L), immediately followed by the library name.

Related

Identical C++ program does not work in another directory on Linux

I have made a simple program that opens a web camera and sets some properties to it, using OpenCV on Debian 9. It has worked fine for some time using this CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project( P )
find_package( OpenCV REQUIRED )
add_executable( capcheck capcheck.cpp )
target_link_libraries( capcheck ${OpenCV_LIBS} )
However, now when I compile the exact same thing, but in another folder, I get this error when running the program:
VIDEOIO ERROR: V4L2: setting property #21 is not supported
VIDIOC_S_CTRL: Invalid argument
Here is the .cpp:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
VideoCapture capture;
Mat sketchMat;
if (!capture.open(1))
{
cout << "ERROR: Could not open camera " << 1 << endl;
return -1;
}
capture.set(CV_CAP_PROP_FRAME_WIDTH, 1920);
capture.set(CV_CAP_PROP_FRAME_HEIGHT, 1080);
capture.set(CAP_PROP_AUTO_EXPOSURE, 0.25);
capture.set(CAP_PROP_EXPOSURE, 0.03);
capture.read(sketchMat);
return 0;
}
Thank you for any help.

Need to find java version number using c++ program

I'm new to C++ programming. So, which libraries or functions should I use in retrieving this info from the registry? Just give me a brief idea about the steps involved in retrieving the java version number from registry. I'm using VC++.
If java paths are properly set, you could just run java -version from code:
Using the code described here How to execute a command and get output of command within C++ using POSIX? :
#include <string>
#include <iostream>
#include <stdio.h>
std::string exec(char* cmd) {
FILE* pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
using like:
int main(void) {
std::cout << exec("java -version");
return 0;
}

I can't figure out how to link msi.lib to my Visual Studio C++ project

I'm trying to write a simple application that will enumerate all the ProductCodes installed on my machine.
I've started a new project in Visual Studio 2013, but whenever I build I get the error:
"LNK2019: unresolved external symbol _MsiEnumProductsExA#32 referenced in function _main"
I've been trying to figure out how to add msi.lib to my project include path, but I can't seem to figure it out.
Here's my code:
#define _WIN32_MSI 300
#include <Windows.h>
#include <iostream>
#include <string>
#include <Msi.h>
using namespace std;
int main() {
// Get a list of all installed MSIs
DWORD index = 0;
TCHAR currentProductCode[40] = {0};
unsigned int result = ERROR_SUCCESS;
// Open an MSI handle
while (ERROR_SUCCESS == result) {
result = MsiEnumProductsEx(NULL, "s-1-1-0",
MSIINSTALLCONTEXT_USERMANAGED | MSIINSTALLCONTEXT_USERUNMANAGED | MSIINSTALLCONTEXT_MACHINE,
index, currentProductCode, NULL, NULL, NULL);
if (result == ERROR_SUCCESS) {
cout << "current ProductCode: " << currentProductCode;
}
index++;
}
return 0;
}
I've been trying to update the project's Property Pages by adding the path to the msi.lib to the "Library Directories" property, but that doesn't seem to work:
This is like Visual Studio 101, what am I missing?!
Goto Configuration Properties>Linker>Input
Add msi.lib in Additional Dependencies Thats it! Make sure you are using same calling conversion, which used to built the lib. i.e either stdcall or cdecl.

XCode Boost Thread Example Compile Error

Here's my basic boost code
#include <iostream>
#include <boost/thread.hpp>
using namespace boost;
using namespace boost::this_thread;
using namespace std;
// Global function called by thread
void GlobalFunction()
{
for (int i=0;i<10;++i)
{
cout << i << "Do something in parallel with main method." << endl;
boost::this_thread::yield();
}
}
void GlobalThreadTest()
{
boost::thread t(&GlobalFunction);
for (int i = 0; i<10; ++i) {
cout << i << "Do something in main method. " << endl;
}
}
int main(int argc, const char * argv[])
{
GlobalThreadTest();
return 0;
}
I'm getting lots of errors like this from xcode
(null): "boost::this_thread::yield()", referenced from:
(null): "boost::detail::thread_data_base::~thread_data_base()",
referenced from: (null): "boost::system::system_category()",
referenced from: (null): "boost::system::generic_category()",
referenced from: (null): "boost::thread::start_thread()", referenced
from:
I have installed boost using macports and the header search paths in xcode is set to
/opt/local/include/
This contains all the .hpp files.
2 Questions
Does boost create *.o files if so where are they stored?
How do I get xcode 4.2 to work with this boost thread example? If there is a flag I have to set, which parameter in xcode 4.2 do I set it in?
Thanks.

apt-get environment variables when spawning "debian rules" file

What are the environment variables made available to debian/rules (often make) when spawned by apt-get during installation of a package under Ubuntu?
I am specifically after the environment variables that would pertain to Gnome's configuration directories. I'd like avoiding "hardcoding" things like ~/.conf/apps/ ... since I have been told these might change like they tend to...
I've been googling like crazy!
Are you looking for the XDG_CONFIG_HOME and related? In particular, note that XDG_CONFIG_HOME doesn't have to exist, and a value of ~/.config is assumed in that case.
Python example
import os
from os import path
app_name = "my_app"
home_config = path.join(
os.environ.get("XDG_CONFIG_HOME") or path.expanduser("~/.config"),
app_name,
)
print "User-specific config:", home_config
C++ example
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>
std::string get_home_config(std::string const& app_name) {
// also look at boost's filesystem library
using namespace std;
string home_config;
char const* xdg_config_home = getenv("XDG_CONFIG_HOME");
if (xdg_config_home && xdg_config_home[0] != '\0') {
home_config = xdg_config_home;
}
else {
if (char const* home = getenv("HOME")) {
home_config = home;
home_config += "/.config";
}
else throw std::runtime_error("HOME not set");
}
home_config += "/";
home_config += app_name;
return home_config;
}
int main() try {
std::cout << "User-specific config: " << get_home_config("my_app") << '\n';
return 0;
}
catch (std::exception& e) {
std::clog << e.what() << std::endl;
return 1;
}
debian/rules gets invoked at package build time (either the source or binary package) It does not get called during apt-get.
In fact, the .deb file (==binary package), does not contain a copy of debian/rules anymore. That file is only in the source package.
Furthermore, packages should normally not try to do things for a particular user, or make use of the configuration of a user. Debian packages are intended for software that is installed system-wide.
Although it's theoretically possible to make a personal package that installs something in /home, such a package is of very limited value.

Resources