Use the glDrawBuffer and glReadBuffer functions in Qt - c++

I would like to use the glDrawBuffer and glReadBuffer functions in Qt using Qt Creator. I tried to do this:
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
This code would not compile, it gave me linking errors like this one:
main.obj:-1: error: LNK2019: unresolved external symbol __imp__glDrawBuffer#4 referenced in function "public: void __thiscall Simple3DWidget::OpenGLWindow::render(void)" (?render#OpenGLWindow#Simple3DWidget##QAEXXZ)
This error basically means that the functions were declared in an included header file but not correctly linked.
After searching for this issue on the web, I found out that I have to use the QOpenGLFunctions_3_1 class. I tried both these codes:
QOpenGLFunctions_3_1 m_openGL31Functions;
m_openGL31Functions.glDrawBuffer(GL_NONE);
m_openGL31Functions.glReadBuffer(GL_NONE);
and:
QOpenGLFunctions_3_1().glDrawBuffer(GL_NONE);
QOpenGLFunctions_3_1().glReadBuffer(GL_NONE);
Both these codes compile correctly, but when I run the program, in both cases, the program crashed and gave me the following error:
Access violation reading location 0x00000090
The strange thing is that I usually get this error when I assign the wrong value to a pointer, but none of these codes contain pointers (or maybe the functions contain pointers which generate this error, in which case there could be a bug in Qt's QOpenGLFunctions_3_1 class?).
What is the correct way of using the glDrawBuffer and glReadBuffer functions in Qt?

This error basically means that the functions were declared in an included header file but not correctly linked.
Correct. You have to link against OpenGL. opengl32.lib on Windows, libGL.so on *nix/Linux, -framework OpenGL on MacOS.
but none of these codes contain pointers (or maybe the functions contain pointers which generate this error, in which case there could be a bug in Qt's QOpenGLFunctions_3_1 class?).
Yes, they do. The OpenGL interface for anything that goes beyond a certain version is loaded at runtime into function pointers. This is what the QOpenGLFunctions class does. Before properly loading these pointers, they are invalid – in fact, depending on the OpenGL version your're using some may be valid and others not; that's why Qt puts the OpenGL version into the class name.
Answer the following questions:
Does the program create a OpenGL context to use?
Is the QOpenGLFunctions_… instance initialized with the context being made active on the calling thread?
Did initialization of the QOpenGLFunctions_… instance succeed?
If you'd answered any of these questions with "no" or "I don't know", that's where your problem is.

Related

Linking to external functions in dynamic libraries with LLVM

In my project, I am emitting LLVM IR which makes calls to external functions in dynamic libraries.
I declare my external functions like:
declare %"my_type"* #"my_function"()
In the external library, functions are declared like:
extern "C" {
my_type* my_function();
}
When I compile the IR and run it, the process immediately crashes. The same behavior happens if I declare and call a nonsense function that I know doesn't exist, so I assume what's happening is that the external function is not being found/linked. (I don't think that the function itself is crashing).
I am using Python's llvmlite library for this task, and within the same process where I JIT and invoke my LLVM IR, I have another python library imported which requires the external dynamic library; so I assume that library is loaded and in-memory.
The procedure I'm using to compile and execute my LLVM code is basically the same as what's in this document, except that the IR declares and invokes an external function. I have tried invoking cos(), as in the Kaleidoscope tutorial, and this succeeds, so I am not sure what is different about my own library functions.
I have tried adding an underscore to the beginning of the function name, but I get the same result. (Do I need to add the underscore in the LLVM function declaration?)
How do I verify my assumption that the process is crashing because the named function isn't found?
How do I diagnose why the function isn't being found?
What do I need to do in order to make use of external functions in a dynamic library, from LLVM code?
Edit: It seems there is indeed trouble getting the function pointers to my external function. If I try to merely print the function address by replacing my calls with %"foo" = ptrtoint %"my_type"* ()* #"my_function" to i64 and return/print the result, it still segfaults. Merely trying to obtain the pointer is enough to cause a crash! Why is this, and how do I fix it?
Edit: Also forgot to mention— this is on Ubuntu (in a Docker container, on OSX).
I figured it out— I was missing that I need to call llvmlite.binding.load_library_permanently(filename) in order for the external symbols to become available. Even though the library is already in memory, the function still needs to be invoked. (This corresponds to the LLVM native function llvm::sys::DynamicLibrary::LoadLibraryPermanently()).
From this answer, it appears calling the above function with nullptr will import all the symbols available to the process.
Oddly, on OSX, I found that the external symbols were available even though load_library_permanently() had not been explicitly called— I'm not sure why this is (perhaps the OSX build of llvmlite itself happened to call the function with nullptr, as above?).

LNK2019, LPCTSTR, and C++ syntax in general

Allow me to preface this question with 2 comments:
1) I'm a C# developer, so I don't have much practice dealing with linker errors in C++ and some standard C++ syntax is a bit unfamiliar to me. I suspect this will be an easy question to the C++ gurus out there.
2) I'm not sure how to ask this question in a way that will be relevant to the masses but I'm open to suggestions/corrections from the community. The problem with lnk2019 errors is that it seems pretty individualized as to what the problem actually is. MSDN has an article that deals with the error generally and Stack Overflow already has a slew of questions with that tag and yet I still can't seem to solve my problem.
On to the details...
I was given an old (VS2005) C++ solution with 42 projects and was asked to try and get it to build. After doing quite a bit of twiddling, I've gotten it down to just 3 projects that won't build. I'd like to focus on just one of them because I think if we can figure that one out, I can do the same things to the other 2 projects to fix them.
Let's start with the error. As you can see, the project in question is named "HttpWire".
Deleting intermediate and output files for project 'Http Wire',
configuration 'Release|x64' Compiling... HttpWire.cpp
Compiling resources... Linking... Creating library
Release\AMD64\HttpWire.lib and object Release\AMD64\HttpWire.exp
HttpWire.obj : error LNK2019: unresolved external symbol "public:
__cdecl THttpWire::THttpWire(char const *)" (??0THttpWire##QEAA#PEBD#Z) referenced in function
CreateConnectionWire Release\AMD64\HttpWire.dll : fatal error LNK1120:
1 unresolved externals
Looks like the linker is upset because the function "CreateConnectionWire" is calling "THttpWire" but for some reason the linker is unable to find it. There is only 1 .cpp file in the project (HttpWire.cpp) and here it is:
#include "THttpWire.h"
BOOL WINAPI DllMain(HINSTANCE hDllInst, DWORD reason, LPVOID reserved)
{
return TRUE;
}
__declspec(dllexport) TConnectionWire *CreateConnectionWire(LPCTSTR connectionString)
{
return new THttpWire(connectionString);
}
__declspec(dllexport) void DeleteConnectionWire(TConnectionWire *connectionWire)
{
delete connectionWire;
}
The #include file, "THttpWire.h" lives in another project called "AirTime Core". It includes several other things and then has the following:
class THttpWire : public TConnectionWire
{
public:
THttpWire(LPCTSTR connectionString);
virtual ~THttpWire();
... (lots of other stuff) ...
}
And then, finally, we have THttpWire.cpp:
#include "THttpWire.h"
...
THttpWire::THttpWire(LPCTSTR connectionString) :
TConnectionWire(connectionString),
hWinHttp(NULL), hSession(NULL), hRequest(NULL),
opTimedOut(FALSE), asyncError(0),
headers(NULL), headersOffset(0), headersLength(0),
availData(0)
{
requestSent = new TSyncEvent(TRUE);
updateToString();
}
This syntax is a bit weird to me... what are we doing here? I mean, I realize this is a constructor, and since THttpWIre appears to inherit from TConnectionWire (according to the .h), then the ":TConnectionWire(connectionString)" makes sense (I'm assuming this is like C# appending ": base()" to constructors of objects that inherit from other objects), but then what is all the other stuff between that and the opening brace (note that TConnectionWire does not appear to inherit from anything else)?
SO...
After doing some searching on MSDN and SO, I've learned the following (please correct me if I'm wrong)
CreateConnectionWire is prefaced by __declspec(dllexport) which simply makes it available to other projects consuming this .dll (as discussed here)
LPCTSTR is a const char* (see MSDN). Note that my projects are set with "Treat wchar_t as Built-in Type: No (/Zc:wchar_t-)" in the property pages. (see the bottom of this article and also this article)
Right now, my primary suspicion is with LPCTSTR. Perhaps it is not defined the same in both projects, which would yield different method signatures... but I don't know how to check for this or fix it if that is the case. Or, perhaps the "/Zc:wchar_t-" thing is affecting it adversely?My next suspicion is that there is something in the string of methods listed in the constructor (with the syntax that I don't understand) that is causing some sort of problem and making the "THttpWire" constructor not available, generally.What do you think? I'd be happy to share any other bits that you think would be useful.
Other information that may or may not be helpful (I'll let you decide)
When I first started with this project, there were several .lib and .h files missing and I've had to go around trying to find them (examples were opends60.lib, mssoap30.lib, WinLUA.h, etc.). It is quite possible I don't have the same version the solution was originally built against.
The projects were all built with "_WIN32_WINNT=0x0400" defined, which appears to mean it was meant to be built against the Windows 2000 SDK (see MSDN). I found something that I thought was the Win 2000 SDK (the oldest one on here, but when I link to that, I get many more errors. Instead, I'm linking to the SDK version 6.1. HOWEVER, this causes WinHttp not to compile because "SOCKADDR_STORAGE" isn't defined for anything "_WIN32_WINNT<0x0501" (windows XP). THUS, I've redefined "_WIN32_WINNT=0x0501" for all of the projects that appear to be related to HttpWire. It is possible I missed one or two.
There is only 1 .cpp file in the project (HttpWire.cpp)
Well, that's a problem because clearly you need more than 1. You also need THttpWire.cpp since it contains the constructor code. The one that the linker cannot find.
Keep the C++ build model in mind, it is very different from C#. Source code files are separately compiled. And then the linker glues all the bits of code together to make the program. Those bits may come from an .obj file created from a .cpp file. Or they could come from a .lib file, a "container" of bits of code.
Which is the likely explanation since you mentioned an "AirTime Core" project. Project + Properties, Linker, Input, Additional Dependencies setting. You need to add the output of the "AirTime Core" project, whatever it is named.

C++ runtime symbol lookup error, ubuntu

I have a C++ function doSth that will call a function "checkFrame" from a class "canMsg" as shown below
#include "canMsg.h"
void doSth(char* canFrame){
map<int, double> returnedData;
CANMsg canMsg;
std::cout<<canFrame <<endl;
canMsg.checkFrame(canFrame);
}
During compilation I receive no error, but when I run it, it executes std::cout<<canFrame <<endl; statement and crashes by creating an error
undefined symbol: _ZNSaIcEC1Ev, version GLIBCXX_3.4
Any ideas how to fix this?
Thanks for the replies. The error was due to my attempt to return a locally declared pointer. After I changed the local pointer variable to a static, it works perfect. The basic idea is C++ does not advocate to return the address of a local variable to outside of the function.
Look this for more information.
I think that kind of problem can arise if things are linked in the 'wrong' order. I suggest you try changing the order of whatever libraries you are passing to the linker.
(I don't actually know why the ordering matters - but it sometimes does.)
This error can occur when dependent library(where _ZNSaIcEC1Ev id defined) was compiled for other version of GLIBC (newer version or much older), that you currently have.
Try to recompile that library with your current environment.
Also you can add nice switch to LDFLAGS of your app: -Wl,--no-undefined. Then you can see any undefined symbols at compile time (not sure if it helps in your situation).

C++ name mangling in a so

Here's what i did:
I changed a .h file from
SomeObj* getCacheObj( int i = 0 );
to
SomeObj* getCacheObj( int i );
SomeObj* getCacheObj();
I recompiled the code (no problems), the changes went to somelib.so (one of many so files). I then replaced the old so on the equipment with this one and got the folowing error when loading the so:
undefined symbol: _ZN13KeypathHelper11getCacheObjEv
Now the strange part is that I've been told this class is only used in this so file (How can I make sure?). I am not that experienced and not sure how to investigate. Any suggestions are welcome.
Update
This particular problem was caused because another so file was using the KeypathHelper class and I only replaced the one containing it. The way I found out which other so needed to be updated was by greping all so's for KeypathHelper.
The _ZN13KeypathHelper11getCacheObjEv symbol is a mangled name for KeypathHelper::getCacheObj() (you can easily translate using c++filt, for example). Given that you have only added a method and whatever is loading the shared object cannot find it makes me think that you either haven't updated the shared object or forgot to provide a definition for KeypathHelper::getCacheObj() (in other words — implement the method).
In order to investigate, you have to see what is failing to resolve the symbol. Usually, developers have a sense for it. Say, if a binary XXX cannot load library YYY due to unresolved symbol, then XXX is using it and it does not appear to be in YYY (or anywhere else for that matter). If there is no sense for that, one can resort to reading ld.so (8) manual page and debug the dynamic linker by using available means like defining LD_DEBUG.
Also, #PlasmaHH has asked a very good question. If the only change you made was to the header file, then you must know that a single function/method with a default value for a parameter is not the same as as two functions/methods where one has a parameter and one does not.
As for your second question about how to make sure that symbol in a shared object is not being used outside — you have to change the symbol visibility so that nobody from the outside is able to link/resolve/use the symbol. For example, see GCC Visibility.
Hope it helps. Good Luck!

Calling a Visual Basic DLL in C++

I have acquired a DLL that was created in Visual Basic from a third party vendor(Sensor DLL.dll). This DLL contains functions for talking to a sensor, and I need to call these functions from a Visual C++ program I am writing. The vendor will not provide a header file, and I do not know Visual Basic. If I had a header file this would be a 15 minute project... instead I am still struggling with it a week later. Please Help!
I am told one function (Get_Data) in the DLL is of the form:
Public Function Get_Data(ByVal Handle As String) As String
I have tried several methods for calling this Get_Data function with no success:
Method 1) the DllImport attribute
#using <mscorlib.dll>
using namespace System::Runtime::InteropServices;
namespace Sensor
{
[DllImport("Sensor DLL.dll", EntryPoint = "Get_Data", CharSet = System::Runtime::InteropServices::CharSet::Unicode)]
BSTR Get_Data(BSTR Handle);
}
//then I call the function
Sensor::Get_Data(Handle);
This method seems to be the closest I have gotten to a sloution. It compiles, but gives the following error when it runs:
An unhandled exception of type 'System.EntryPointNotFoundException' occurred
Additional information: Unable to find an entry point named 'Get_Data' in DLL 'Sensor DLL.dll'.
I have tried various datatype combinations/permutations besides BSTR including BSTR*, wchar_t, int, etc. It is possible that I missed one, but each datatype returns the same error.
Method 2) dllimport storage-class attribute
__declspec(dllimport) BSTR Get_Data(BSTR Handle);
//then I call the function
Get_Data(Handle);
This method is confusing to me because I don't specify the DLL I want to import from. I have copied the DLL to the project folder and I have added it to the project manually, so hopefully that means it can be found. When I compile the linker returns the following errors:
error LNK2028: unresolved token (0A00034F) "wchar_t * __cdecl Get_Data(wchar_t *)" (?Get_Data##$$FYAPA_WPA_W#Z) referenced in function "int __cdecl main(void)" (?main##$$HYAHXZ)
error LNK2019: unresolved external symbol "wchar_t * __cdecl Get_Data(wchar_t *)" (?Get_Data##$$FYAPA_WPA_W#Z) referenced in function "int __cdecl main(void)" (?main##$$HYAHXZ)
I suspected maybe this meant I should be using wchar_t or wchar_t* instead of BSTR, but changing to either datatype results in the same error.
Method 3) GetProcAddress
typedef BSTR (*Get_Data_Ptr)(BSTR Handle);
HINSTANCE LoadMe;
LoadMe = LoadLibraryA("Sensor DLL.dll");
if (!LoadMe)
std::cout << "\nDLL failed to load!\n";
Get_Data_Ptr LibMainGet_Data;
LibMainGet_Data = (Get_Data_Ptr)GetProcAddress(LoadMe,"Get_Data");
//then I call the function
LibMainGet_Data(Handle);
This will compile, but gives the following error when run:
An unhandled exception of type 'System.AccessViolationException' occurred
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
When I mouse over the various parts of this code in debug mode it seems that, like the first method, it was also unable to find the 'Get_Data' entry point in the DLL.
Has anyone called functions from a VB DLL using C++ when you haven't made the DLL yourself and you don't have .idl files, etc? Does anyone have a working example like this you could share?
Thanks!
A VB6 DLL is normally a COM server. You do in fact have the equivalent of a .h file, it has a type library embedded in it. Start this off with Project + Properties, Common Properties, Framework and References. Add New Reference button, Browse tab, select the DLL.
Next, View + Object Browser. You should see the generated Interop library in the list. Open the node to see what is there. You write normal managed code, like gcnew, to create the COM object and call the interface methods. You do need some minimum documentation on the available methods to have a guess at how they should be called.
I believe the missing piece is the calling convention. C++ has its own function calling convention different than VB6 (I assume VB6 since you haven't stated VB.NET explicitly). VB6 uses STDCALL convention whereas C++, depending on the vendor, uses a different calling convention termed __cdecl, which is why you see the __cdecl in the compiler error line for method #2. It assumes your external function is using that calling convention by default. Calling convention is a set of rules describing how functions call one another; specifically about how registers are used, what order parameters are delivered in, how by-value / by-reference is determined, etc.
I would suggest sticking with method #3 since method #1 is for Managed C++ which is not standard C++, and method #2 is unfamiliar to me and looks a bit ambiguous. What you want to try is declaring the function pointer typedef to use STDCALL.
typedef BSTR (__stdcall *Get_Data_Ptr)(BSTR Handle);
In the OLE/COM viewer, in order to view the COM type library in a dll/exe/... you have to open it by using "File->View TypeLib" instead of "File->Bind to File"
It sounds like the DLL isn't actually exporting a function named Get_Data. Open up a command prompt and use dumpbin to get the list of exports of the DLL, e.g.:
dumpbin /exports "Sensor DLL.dll"
(dumpbin.exe is located in VC\bin within your Visual Studio install folder, which istypically something like C:\Program Files\Microsoft Visual Studio 10.0).
Then, replace Get_Data with the actual entry point and see if you have any better luck.
A Visual basic program normally needs a runtime to execute.
If you have a COM object (implemented in VB) use the COM API to communicate with it from C++. You will have to register the COM first. Here is a thread that explains hot to do that: http://forums.devx.com/archive/index.php/t-87059.html
If you use a .NET language, use the method of Hans Passant with a reference that will create an interop dll for you. This is far much easier.
Method 1: Do not do that, if you have a COM object that you want to use from a .NET environment, reference it.
Method 2: You get errors because you lack the the .lib file to properly link to the DLL (statically dynamically linking)
Method 3: Would be a pure dynamic solution but you have to know the exact names of the methods in the DLL. These may vary according to the parameters and calling convention used. This is very similar (actually identical, I would say) to the issue you face with your Method 1 solution. The name of the method is for yure not "Get_Data" but something else. With a tool like the dependency viewer you can have a look at the exported names.
Even Method 3 with the right names is likely to fail because if it is a COM object you will need some environment called Appartment to use the COM objects. You "enter" this appartment by calling CoInitialize. This creates some magical stuff in the TLS (Thread Local Storage) to perform the COM magic. I hope this explains why your tries will be pointless if the DLL you have is happening to be a COM component, what is quite likely according to the ATL like naming we can see.
EDIT:
I forgot to say that you can also easily see what is inside the dll if it is a COM with the OLE/COM Viewer (normally if you have a compiler you will have such a tool around).