Possible to hide cv-prefixed functions in OpenCV? - c++

I'm using C++, and compiling & linking to OpenCV2 using "g++". One thing that bothers me is that all of the old cv-prefixed functions are still available and "pollute" my application.
Is it possible to make the OpenCV1 C cv-prefixed functions unavailable in the scope of my application and just keep the OpenCV2 cv:: namespaced ones?
Note: I haven't written C in a while, so please let me know if this is a silly question.

It depends on what do you really need. If you just want to make this code:
CvArr *arr;
cvAvg(arr);
cvAcc(arr, arr);
"not working" - you can just add this:
#define cvAvg nothing_interesting_cvAvg
#define cvAcc nothing_interesting_cvAcc
//you can change nothing_interesting_... to anything, but you can't use the same text more than once
//you include files
//...
//after your include files
#undef cvAvg
#undef cvAcc
before including any OpenCV file. If you now try to compile code you will see:
error C3861: 'cvAvg': identifier not found
If you change you code to use nothing_interesting_cvAvg(arr); instead of cvAvg(arr);, it will compile fine, but linker will fail, because:
: error LNK2019: unresolved external symbol _nothing_interesting_cvAvg referenced in function _main
Note that this will work only for this 2 functions, so you will have to find all functions which you want to "disable" and write similar code manually.
Functions which use "deactivated" functions will work fine, because they are already compiled, linked, etc - you will just call them from some files without changing anything in this files.

Related

error LNK2001: unresolved external symbol (every static member of SFML library can't be loaded)

So, I have problem, when try to use any of static members of SFML Library like sf::RenderState::Default or sf::Color::Blue.
error LNK2001: unresolved external symbol "public: static class sf::RenderStates const sf::RenderStates::Default" (?Default#RenderStates#sf##2V12#B)
But when I comment lines, I have access to sf::window (it be created, but can't draw anything, because sf::Drawble has sf::RenderState::Default as standart argument).
I checked everything including linker and compiler in Solution properties in Visual Studio (I have VS19).
P.S. I use the latest version of SFML (2.5.1) and Visual C++20.
Thanks for your help.
The troubleshooting steps I would undertake in this situation go from easiest to the inverse of that.
If I check the declaration of sf::RenderState::Default, can it be found?
If I create a new project with just this feature used, does the error persist?
If I redo my linking and directory searches, is the problem fixed?
Do I have a version compatible with my compiler?
Furthermore, the amount of information you've given about your environment is not enough to speculate on what the issue could be. It might be helpful to post your version of SFML, your compiler (and kind), what your project is like (shorthand.)
SFML can be compiled from source if necessary. Sometimes, using an incompatible version on accident will not show any issues on many basic things until you run into weird errors.
See this document on compiling SFML from source:
https://www.sfml-dev.org/tutorials/2.5/compile-with-cmake.php
So, thanks for AlixianaBritmonkey, I managed with this problem. I just create new project and moved every file. I don't know why problem occured before, but my solution helped.

CGAL Skeletonization compile errors

I'm new to C++ and CGAL, previously I worked mainly with C#.
I installed CGAL as described on https://www.cgal.org/download/windows.html and all steps finished successfully.
Then I looked to a CGAL 'Hello world' (https://doc.cgal.org/latest/Manual/Kernel_23_2points_and_segment_8cpp-example.html); here I had no problem also; all the code was compiled and run propertly.
But when I tried with more complex things I got a strange issue. For example I tried to compile Skeletonization (https://doc.cgal.org/latest/Surface_mesh_skeletonization/Surface_mesh_skeletonization_2simple_mcfskel_example_8cpp-example.html);
here I got a number of errors like these:
C2039 ''extract_mean_curvature_flow_skeleton'': is not a member of ''CGAL''
C2039 ''Matrix'': is not a member of ''CGAL::Default''
C2039 ''Vector'': is not a member of ''CGAL::Default''
As far as I understand it the #include lines processed without errors, all needed headers exist.
I tried to search the answer and found this: http://cgal-discuss.949826.n4.nabble.com/Problem-on-Surface-mesh-deformation-td4661042.html
Unfortunately I don't be sure my case is similar and I don't know what exactly do the line #define CGAL_EIGEN3_ENABLED as recommended there.
In any case I tried to add it and got the same errors as previous if this #define inserted after #include ; in different case arise a lot of errors like this:
LNK2019 unresolved external symbol __imp___gmpq_add referenced in function "class CGAL::Gmpq __cdecl CGAL::operator+(class CGAL::Gmpq const &,class CGAL::Gmpq const &)" (??HCGAL##YA?AVGmpq#0#AEBV10#0#Z)
I work with VS 2017, in Additional library directories I added:
$(CGAL_DIR)/lib/Debug;$(CGAL_DIR)/lib
in Additional include directories:
$(CGAL_ROOT)\include;$(CGAL_ROOT)\auxiliary\gmp\include;
$(CGAL_DIR)\include;$(BOOST_INCLUDEDIR)
maybe some needed libraries or include directories are missing here?
All the components (CGAL, boost, QT) installed in 64 bits versions as well as test project.
UPD: The question is solved!
The answer was extremely simple (please note I'm new in C++):
1. I loaded and unzip EIGEN (it need not to install); for convenience I create also EIGEN_DIR variable;
2. I added to Additional Include Directories: $(EIGEN_DIR);
3. I added before #include statements #define CGAL_EIGEN3_ENABLED;
4. I added to Additional Dependencies such libs:
$(CGAL_ROOT)\auxiliary\gmp\lib\libmpfr-4.lib
$(CGAL_ROOT)\auxiliary\gmp\lib\libgmp-10.lib
and it start to work!

search for unresolved references that should have been ifdef'ed out

I hope this is an interesting question. I'm trying to find the source of an unresolved external symbol. I have debug code that uses a global file pointer if debugging is turned on. All of this debugging code is supposed to be protected by #ifdef, like:
#ifdef DO_XLL_DEBUG
fprintf(debugPointer, "hello\n);
...
#endif
When I define DO_XLL_DEBUG, all is well. If I undef DO_XLL_DEBUG, everything compiles (I do a rebuild all just in case), but it fails at the link step, not finding debugPointer.
So, the question is, is there an easy way to find where I failed to #ifdef around the debug code? I can think of several not so easy ways.
I'm using Visual Studio 2005. This is a C++ project.
Thanks!
[EDIT]
Thanks for all the suggestions. Turns out the problem was in someone else's code that is not part the corresponding project I'm working on in Linux (where I do most of my work), so no wonder I didn't find it right away.
Just define some incompatible debugPointer and let the compiler point you at all the places where it's accidentially used or redefined. Maybe like this:
#ifndef DO_XLL_DEBUG
#define debugPointer static_assert(false,"damn it!");
#endif
(given that you don't have other variables, parameters, etc. which are called debugPointer)

Getting "error LNK2001: unresolved external symbol _gnutls_free" when using GnuTLS 3.1.6 from Visual Studio 2012

I am attempting to build a project in Visual Studio 2012 that uses GnuTLS. I downloaded the latest official Windows build from the website, and created a link library by running lib /def:libgnutls-28.def in the bin directory form a Visual Studio command prompt.
After adding a typedef long ssize_t, the code compiles fine, but linking fails with the following error:
source_file.obj : error LNK2001: unresolved external symbol _gnutls_free
C:\Path\to\executable.exe : fatal error LNK1120: 1 unresolved externals
I am calling gnutls_free to free some memory allocated and returned by the library. If I remove the call to gnutls_free, the project links successfully. Given that gnutls_free is just a global variable (containing a function pointer) exported by the library, I'm not sure why accessing it results in an unresolved reference to a different symbol. I have verified that gnutls_free is not #defineed to anything.
As a test, I tried doing gnutls_free_function test = gnutls_free; which also resulting in the link error. Running grep -w -r _gnutls_free . on the GnuTLS source code returns nothing, so I am at a loss.
Any ideas for getting this working would be greatly appreciated.
EDIT:
Adding __declspec(dllimport) to the declaration of gnutls_free in gnutls.h allows the link to succeed. Is there any way to accomplish this without maintaining a custom version of the header file?
There doesn't seem to be a way to have the linker or import library automatically dereference the IAT's pointer to the data item the same way that is done for functions (via a small trampoline function that is statically linked into the module importing the function). The __declspec(dllimport) attribute tells that compiler that this dereferencing needs to be done so it can insert code to perform the dereferencing of the IAT pointer implicitly. This allows exported data to be accessed and for functions allows the compiler to call the imported function via an indirect call through the IAT pointer rather than by calling the trampoline function.
See a couple of Raymond Chen's articles about dllimport for a good explanation of what goes on for function calls (he didn't discuss importing data, unfortunately):
Calling an imported function, the naive way
How a less naive compiler calls an imported function
The MS linker or import library doesn't have a mechanism to help the compiler get imported data in a 'naive' way - the compiler needs the the __delcspec(dllimport) hint that an extra dereference through the IAT is needed. Anyway, the point of all this is that it seems there's no way to import data except by using the __declspec(dllimport) attribute.
If you want to avoid modifying the gnutls distribution (which I can understand), here's one rather imperfect workaround:
You can create a small object file that contains nothing but a simple wrapper for gnutls_free(); since gnutls_free() has an interface with no real dependencies, you can have the necessary declarations 'hardcoded' instead of including gnutls.h:
typedef void (*gnutls_free_function) (void *);
__declspec(dllimport) extern gnutls_free_function gnutls_free;
void xgnutls_free(void* p)
{
gnutls_free(p);
}
Have your code call xgnutls_free() instead of gnutls_free().
Not a great solution - it requires your code to call a wrapper (so it's particularly not great if you'll be incorporating 3rd party code that might depend on gnutls_free()), but it might be good enough.

OpenCV 2.3 with Qt 4.3.7

I have successfully build and ran both Qt 4.3.7 and OpenCV 2.3 with Qt enabled. When I start a window using:
cvNamedWindow( "video", 0 );
I successfully load a full Qt interface! wonderful :)
However!! when I use the command
void callbackButton(int state, void* userdata){
int x;
x=3;
}
cvCreateButton(nameb2,callbackButton,nameb2,CV_CHECKBOX,0);
I get the error message
error LNK2001: unresolved external symbol _cvCreateButton
I don't understand as the Qt interface already has lots of buttons on it? could someone please explain what I am missing from the include that could cause this?
Thanks!
You use the wrong parameters for to call to cvCreateButton. According to the documentation here the signature of the function is
cvCreateButton(const char* button_name CV_DEFAULT(NULL), CvButtonCallback on_change CV_DEFAULT(NULL), void* userdata CV_DEFAULT(NULL), int button_type CV_DEFAULT(CV_PUSH_BUTTON), int initial_button_state CV_DEFAULT(0)
and sample calls are:
cvCreateButton(NULL,callbackButton);
cvCreateButton("button2",callbackButton,NULL,CV_CHECKBOX,0);
cvCreateButton("button3",callbackButton,&value);
cvCreateButton("button5",callbackButton1,NULL,CV_RADIOBOX);
cvCreateButton("button6",callbackButton2,NULL,CV_PUSH_BUTTON,1);
and the declaration of the callback function has to be:
CV_EXTERN_C_FUNCPTR( *CvButtonCallback)(int state, void* userdata));
You get a linking error and not a compiler error because cvCreateButton has extern "C" linkage - which means that parameters cannot be checked at compile time.
I solved this issue by calling the function cv::createButton instead of cvCreateButton (which is if I am correct the way to call methods in OpenCV2).
The third argument must be a void*. Change to:
cvCreateButton(nameb2,callbackButton,NULL,CV_CHECKBOX,0);
and it will work.
Edit
The statement above was given an error.
The third needed argument is a "void *" - this is compatible with anything and thus neither C nor C++ should have a problem with what you were providing. You can not raise a linker error with that.
The only reason a linker error can be raised by coding is when you don't use prototypes (forgot to use the header file) in C++ and then C++ creates a mangled name on its own that wont be part of any library. In such a case the compiler will first tell you with a warning at compile time that you are missing the prototype (for C and C++) - and then the linker will probably raise an error (for c++ only).
If you don't see a prototype warning from the compiler then that is not your problem.
This is a linking error.
Try to add the opencv .lib file (or files) to the project libraries path.
This may help : VS2010 OpenCV.
Edit
Refined problem: Even if adding any OpenCV libary to your project the linking will fail.
Reason: The symbol is often simply not there in the libraries.
Solution: You have to change a few settings and compile them on your own.
See also: openCV 2.2 createButton LNK 2019 error in Visual Studio 2010