OSDynamicCast not compiling in basic driver kit example - c++

I've got a very simple driver kit driver. It's almost boiler plate.
I'm getting a build failure when trying to use OSDynamicCast, as per the below
kern_return_t IMPL(MyHIDDriver, NewUserClient) {
IOService* client;
auto ret = Create(this, "MyTest", &client);
*userClient = OSDynamicCast(IOUserClient, client);
return ret;
}
My use of OSDynamicCast is giving me the following issue.
Use of undeclared identifier 'gIOUserClientMetaClass'; did you mean 'gIOUserServerMetaClass'?
Before adding the NewUserClient override, the driver was running fine (I've observed it in the IORegistry).
I'm not sure what I'm missing here in Xcode that would cause this issue. Samples I've referenced, such as this, do exactly what I'm doing with OSDynamicCast.

Is the IOUserClient header #included somewhere in this compilation unit? It sounds like you're simply missing
#include <DriverKit/IOUserClient.h>
Entirely unrelated to the issue you're experiencing, but you may want to initialise the client variable to a nullptr to avoid issues with undefined behaviour in case Create fails:
IOService* client = nullptr;
The documentation does not guarantee that it will be set to this automatically if the call fails, so the subsequent OSDynamicCast would be exposed to undefined behaviour.

Related

Instantiating boost::beast in dynamic library causes a crash

I'm trying to implement a very simple, local, HTTP server for my C++ application — I'm using XCode on macOS. I have to implement it from within a dynamically loaded library rather than the "main" thread of the program. I decided to try using boost::beast since another part of the application uses boost libraries already. I'm trying to implement this example, but within the context of my library, and not as part its main program.
The host application for this library calls on the following function to start a localhost server, but crashes when instantiating "acceptor":
extern "C" BASICEXTERNALOBJECT_API long startLocalhost(TaggedData* argv, long argc, TaggedData * retval) {
try {
string status;
retval->type = kTypeString;
auto const address = net::ip::make_address("127.0.0.1");
unsigned short port = static_cast<unsigned short>(std::atoi("1337"));
net::io_context ioc{1};
tcp::acceptor acceptor{ioc, {address, port}}; // <-- crashes on this line
tcp::socket socket{ioc};
http_server(acceptor, socket);
ioc.run();
status = "{'status':'ok', 'message':'localhost server started!'}";
retval->data.string = getNewBuffer(status);
}
catch(std::exception const& e)
{
string status;
//err_msg = "Error: " << e.what() << std::endl;
status = "{'status':'fail', 'message':'Error starting web server'}";
retval->data.string = getNewBuffer(status);
}
return kESErrOK;
}
When stepping through the code, I see that XCode reports an error when the line with tcp::acceptor ... is executed:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x783c0a3e3f22650c)
and is highlighted at the single line of code in a function in scheduler.h:
//Get the concurrency hint that was used to initialize the scheduler.
int concurrency_hint() const
{
return concurrency_hint_; //XCode halts here
}
I'm debating as to whether or not I should include a different C++ web server, like Drogon, instead of boost::beast, but I thought I would post here to see if anybody had any insight as to why the crash is happening in this case.
Update
I found a fix that is a workaround for my particular circumstances, hopefully it can help others running into this issue.
The address to the service_registry::create static factory method resolves correctly when I add ASIO_DECL in front of the methods declaration in asio/detail/service_registry.hpp.
It should look like this:
// Factory function for creating a service instance.
template <typename Service, typename Owner>
ASIO_DECL static execution_context::service* create(void* owner);
By adding ASIO_DECL in front of it, it resolves correctly and the scheduler and kqueue_reactor objects initialize properly avoiding the bad access to concurrency_hint().
In my case I am trying to use non-Boost ASIO inside of a VST3 audio plug-in running in Ableton Live 11 on macOS on an M1 processor. Using the VST3 plug-in in I'm getting this same crash. Using the same plug-in in other DAW applications, such as Reaper, does not cause the crash. It also does not occur for Ableton Live 11 on Windows.
I've got it narrowed down to the following issue:
In asio/detail/impl/service_registry.hpp the following method attempts to return a function pointer address to a create/factory method.
template <typename Service>
Service& service_registry::use_service(io_context& owner)
{
execution_context::service::key key;
init_key<Service>(key, 0);
factory_type factory = &service_registry::create<Service, io_context>;
return *static_cast<Service*>(do_use_service(key, factory, &owner));
}
Specifically, this line: factory_type factory = &service_registry::create<Service, io_context>;
When debugging in Xcode, in the hosts that work, when inspecting
factory, it shows the correct address linking to the service_registry::create<Service, io_context> static method.
However, in Ableton Live 11, it doesn't point to anything - somehow the address to the static method does not resolve correctly. This causes a cascade of issues, ultimately leading up to trying to invoke the factory function pointer in asio/asio/detail/impl/service_registry.ipp in the method service_registry::do_use_service. Since it doesn't point to a proper create method, nothing is created, it results in uninitialized objects, including the scheduler instance.
Therefore, when calling scheduler_.concurrency_hint() in kqueue_reactor.ipp the scheduler is uninitialized, and the EXC_BAD_ACCESS error results.
It's unclear to me why under some host processes, dynamically loading the plug-in cannot resolve the static method address, but others have no problem. In my case I compiled asio.hpp for standalone ASIO into the plug-in directly, there was no linking.
The best guesses I can come up with are
maybe your http_server might start additional threads or even fork. This might cause io_context and friends to be accessed after startLocalhost returned. To explain the crash location appearing to be at the indicated line, I could add the heuristic that something is already off during the destructor for ioc
the only other idea I have is that actually the opening/binding of the acceptor throws, but due to possible incompatibilities of types in the shared module vs the main program, the exception thrown is not actually caught and causes abnormal termination. This might happen more easily if the main program also uses Boost libraries, but a different copy (build/version) of them.
In this case there's a simple thing you can do: split up initialization and use the overloads that take error_code to instead use them.

How to solve a function acting differently based on callsite?

Not sure how to word the title so feel free to rename, but the issue I'm having is that I've got a function that works in one project, but fails in another. Below is rough pseudocode to show that one call in LibraryProject works, whereas the call in GameProject doesn't.
In ChildClass::do_stuff, the win32_window HWND is valid, whereas the second one, failed_win32_window is null and glfw throws an error saying it isn't initialized, despite it already having been initialized (since the first glfw call was successful and I've manually stepped through to verify it was):
GLFWError #65537 Happen, The GLFW library is not initialized
Here's pseudocode showing the two projects, and the files. GLFW is set initialized properly since if I do all my glfw logic within LibraryProject, the window shows up as normal.
//LibraryProject
////library_header.h
class ParentClass {
GLFW* _mainWindow; //filled in elsewhere in the real code
HWND getWin32Window() { return glfwGetWin32Window(_mainWindow); }
}
//GameProject
////game_header.h
#include "library_header.h" //from other Project
class ChildClass : public ParentClass {
void do_stuff() {
HWND win32_window = this->getWin32Window(); //this works because it goes down into LibraryProject.dll's module
HWND failed_win32_window = glfwGetWin32Window(_mainWindow); //but literally the same call here doesn't because it happens within GameProject.exe
}
}
////game_body.cpp
void function_called_elsewhere_in_game() {
//called from GameProject.exe
auto child = ChildClass();
child.do_stuff();
}
I'm not sure if this is an issue with glfw and my setup, or just my misunderstanding how projects and dependencies work.
Things I've tried:
Downloading the latest glfw3
Rebuilding the entire solution
Toggling with References and Linking Dependency Inputs
Things to note:
This is happening in the main thread, nothing else is using glfw at the same time. Its 100% reproducible too.
glfw3.lib is always being created in my GameProject output folder, based on the one inside LibraryProject
Stepping through the disassembly for each of the two glfwGetWin32Window calls has different addresses in disassembly, leading me to believe they're two different copies of the same library, but I'm not sure.
This is not an issue with cocos2d, the game engine I'm using as starting a blank project and calling glfwGetWin32Window(..) returns a valid pointer, even in GameProject, so there's something that I'm doing wrong, but I don't know what.
Images showing off the actual behaviour. magnolia_cocos_proj is GameProject and is the exe I'm running, and libcocos2d is LibraryProject I'm using as a DLL (I'm unfamiliar with the details of how linking and dlls work).
win32_window has valid value
definition of getWin32Window() to be 100% sure. Notice the module is in libcocos2d.dll now.
after going over the second line, the error throws and the second window is null
As I understood from "glfw3.lib is always being created" you use static linking. Static linking of a lib to different dll and exe lead to duplicating of all static memory of the lib. You should use a dynamic library for GLFW in the case. It's glfw3dll.lib.
There are two main cases why this error could appear:
GLFWError #65537 Happen, The GLFW library is not initialised
Case One :
The mentioned error occurs if a GLFW function was called that mustn't be called unless the library is initialised. So, you need to initialise GLFW before calling any function that requires initialisation.
Read an API introduction for reference. Use if-else statement for handling glfwInit() and errors.
Reading Moving from GLFW 2 to 3 is also useful.
Case Two :
This error quite often occurs in the case you have previous versions of GLFW installed on your machine. GLFW3 doesn't like running along with previous version installed. So, delete all the GLFW libraries and linkers and reinstall the latest GLFW 3 from scratch.
Hope this helps.

Include Alien in portable app, C++

Ok, I've searched quite a bit, but seem unable to find an answer or example for how to achieve this.
Basically, I have an app that is designed to be portable (built using VC++ in VS2010, but no MFC or managed components, raw WinAPI). I have Lua 5.2 built into it and allow the user to write scripts inside the application. I have multiple glued functions which are exposed to the Lua scripts which handle various WinAPI calls.
However, what I'd like to be able to do is allow the user to write a script in which looks something like this:
require[[Alien/alien]]
local mb = alien.User32.MessageBoxA
mb:types{ 'long', 'long', 'string', 'string', 'long' }
print(mb(0, "Hello World!", "Test", 64))
I simply cannot seem to find a way to do this. I do not want to require the user to install Lua for Windows and, ideally, there be no core.dll and struct.dll from alien; when I tried to do something with those DLLs in ./alien/, it was crashing in Lua5.1.dll because I had LuaForWindows installed, I uninstalled LFW, and then it just states that Lua5.1.dll is missing. I have Lua 5.2 built into my app, so obviously the core/struct DLLs from the Alien rock are expecting Lua5.1.dll to be in the path.
I made a worthless attempt to try to including the Alien src into the project, but doesn't seem to work that way either.
Any ideas would be greatly appreciated. I'd prefer it all be contained in my app, but I'll settle for a solution which involves including the libraries in my project to build and bundle in the distribution if that's the only alternative.
Thanks!
UPDATE:
Ok, thank you Ben Voigt! I think I'm almost there. I've pulled in core.c and struct.c and made sure all the paths are there for libffi. Everything compiles without issue, until I try to call luaopen_alien_core in core.c (the alien.core src file), claiming the identifier is undeclared. I've tried to declare the function signature in my separate source file that's trying to make the call, the compile gets further, but fails complaining of an unresolved external.
Clearly this is likely now a general C++ issue (as I'm only a novice in this area). Here's the general idea of what I have:
//core.c (from Alien project)
(...)
int luaopen_alien_core(lua_State *L) {
alien_register_library_meta(L);
alien_register_callback_meta(L);
alien_register_function_meta(L);
alien_register_buffer_meta(L);
lua_getglobal(L, "alien");
if(lua_isnil(L, -1)) {
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "alien");
}
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, -3, "core");
alien_register_main(L);
return 1;
}
//mysource.c (the file attempting to call luaopen_alien_core(L))
void initLua()
{
L = luaL_newstate();
luaL_openlibs(L);
luaopen_alien_core(L);
(...)
}
This fails to start compiling, issuing the error:
error C3861: 'luaopen_alien_core': identifier not found
Which makes sense, so I add the following line to myheader.h:
int luaopen_alien_core(lua_State *L);
This compiles, but fails to link with:
error LNK2001: unresolved external symbol "int __cdecl luaopen_alien_core(struct lua_State *)" (?luaopen_alien_core##YAHPEAUlua_State###Z)
I've tried several things I can think of, with my limited experience, but nothing will satisfy this error. I even tried to move the contents of core.c into mysource.c, but that creates a whole different mess and seemed to be the wrong way to go as it is.
I'm hoping, and imagining, this is something really stupid, but I'm just not sure how to get it to call luaopen_alien_core, which seems to be the final piece I need.
Thanks again!
}
I imagine that the require directive both loads a dynamic library and adds its contents to the active Lua engine.
By linking alien directly into your code, you obviate the need for the dynamic library. But the content enumeration code won't have run, and you can't use require to run it, or else it'll go looking for a DLL file (along with all the DLL dependencies).
So, you should find out what functions that require directive calls after loading the DLL, and call those when creating a Lua engine. Then it will neither be necessary nor allowed for the script to start with require [[Alien/alien]], but Alien objects will be available.

Why do I receive a SIGSEGV signal while using the Aria robotics API?

I am using the Aria C++ programming libs for mobile robots (http://robots.mobilerobots.com/wiki/ARIA). I am new to this API so I wanted to start with a simple action class derived from ArAction. Now I tried to develop a small test program (an ArAction) in order to
control a simulated p3dx robot via MobileSim. Development takes place under Ubuntu 10.10, using gcc 4.4.5. Making (compiling) my code works fine, without errors. I can also set the desired speed for example in my ArAction's fire() method, and the simulation is also working as desired.
But, unfortunately, I can't use the ArRobot object attached to the ArAction I am overriding. The problem is that none of the member functions of the ArRobot object seems to work. For example, calling getVel() or getCompass() always returns a zero value. And when I call the hasFrontBumpers() method the program even crashes with the error message "Aria: Received signal 'SIGSEGV'. Exiting.". As soon as I remove this method call and recompile the error is also gone again...
Here is the relevant code that leads to the crash:
ArActionDesired * forward::fire(ArActionDesired d)
{
desiredState.reset();
ArRobot *r = getRobot();
if(r == NULL)
{
printf("ArRobot = NULL\n");
deactivate();
return &desiredState;
}
printf("ok, ArRobot is not NULL, check for bumpers...\n");
r->hasFrontBumpers(); // <-- this leads to the SIGSEV-based "crash"
return &desiredState;
}
Any ideas what I am missing here -- is it a problem with my coding, or with the simulation environment? Thanks in advance for your help!
Kind regards, Matthias
ok, found it out now -- for the records: the Aria libs in version 2.7.2 are based on gcc-3 and libstdc++ 5, but Ubuntu 10.10 (which I am using) is shipped with gcc-4 and libstdc++ 6 per default. So I had to manually install the older versions of both packages, now my code is running fine...
cheers!
Calling hasFrontBumpers() for a p3dx from the fire() works fine for me on a similar Linux platform. If something is wrong, it is not in this method but in the initialization of the system. A reason for the non-moving robot could be that robot.enableMotors() hasn't been called.

What has to be Glib::init()'ed in order to use Glib::wrap?

So I'm trying to make use of a GtkSourceView in C++ using GtkSourceViewmm, whose documentation and level of support give me the impression that it hasn't been very carefully looked at in a long time. But I'm always an optimist :)
I'm trying to add a SourceView using some code similar to the following:
Glib::RefPtr<gtksourceview::SourceLanguageManager> source_language_manager = gtksourceview::SourceLanguageManager::create();
Glib::RefPtr<gtksourceview::SourceLanguage> source_language = Glib::wrap(gtk_source_language_manager_guess_language(source_language_manager->gobj(), file, NULL));
Glib::RefPtr<gtksourceview::SourceBuffer> source_buffer = gtksourceview::SourceBuffer::create(source_language);
gtksourceview::SourceView* = m_source_view = new gtksourceview::SourceView(source_buffer);
m_vbox.pack_start(*m_source_view);
Unfortunately, it spits out the warning
(algoviz:4992): glibmm-WARNING **:
Failed to wrap object of type
'GtkSourceLanguage'. Hint: this error
is commonly caused by failing to call
a library init() function.
and when I look at it in a debugger, indeed the second line above (the one with the Glib::wrap()) is returning NULL. I have no idea why this is, but I tried to heed the warning by adding Glib::init() to the begining of the program, but that didn't seem to help at all either.
I've tried Google'ing around, but have been unsuccessful. Does anyone know what Glib wants me to init in order to be able to make that wrap call? Or, even better, does anyone know of any working sample code that uses GtkSourceViewmm (not just regular GtkSourceView)? I haven't been able to find any actual sample code, not even on Google Code Search.
Thanks!
It turns out, perhaps not surprisingly, that what I needed to init was:
gtksourceview::init();
After this, I ran into another problem with one of the parameter to gtksourceview::SourceLanguageManager, but this was caused by a genuine bug which I subsequently reported and was promptly fixed. So everything's working great now!
I use gtkmm. Typically you have to initialize things with something like :
_GTKMain = new Gtk::Main(0, 0, false);
Of course do not forget :
delete _GTKMain;
Check here for details :
http://library.gnome.org/devel/gtkmm/2.19/classGtk_1_1Main.html
(Sorry but the link option does not work ...)