Bug 1418328
Summary: | nbdkit-plugin.h c++ support | ||||||
---|---|---|---|---|---|---|---|
Product: | [Community] Virtualization Tools | Reporter: | Shaun McDowell <shaunjmcdowell> | ||||
Component: | nbdkit | Assignee: | Richard W.M. Jones <rjones> | ||||
Status: | CLOSED UPSTREAM | QA Contact: | Fedora Extras Quality Assurance <extras-qa> | ||||
Severity: | unspecified | Docs Contact: | |||||
Priority: | unspecified | ||||||
Version: | unspecified | CC: | eblake, ptoscano, rjones | ||||
Target Milestone: | --- | Keywords: | Reopened | ||||
Target Release: | --- | ||||||
Hardware: | Unspecified | ||||||
OS: | Unspecified | ||||||
Whiteboard: | |||||||
Fixed In Version: | Doc Type: | If docs needed, set a value | |||||
Doc Text: | Story Points: | --- | |||||
Clone Of: | Environment: | ||||||
Last Closed: | 2017-02-01 17:54:13 UTC | Type: | Bug | ||||
Regression: | --- | Mount Type: | --- | ||||
Documentation: | --- | CRM: | |||||
Verified Versions: | Category: | --- | |||||
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |||||
Cloudforms Team: | --- | Target Upstream Version: | |||||
Embargoed: | |||||||
Attachments: |
|
Description
Shaun McDowell
2017-02-01 14:59:25 UTC
Fixed upstream: https://github.com/libguestfs/nbdkit/commit/3647fe831a5c6d12832c4e48d1337489fd44fa59 The upstream fix doesn't catch this register plugin macro #define NBDKIT_REGISTER_PLUGIN(plugin) \ extern struct nbdkit_plugin * \ plugin_init (void) \ { \ (plugin)._struct_size = sizeof (plugin); \ (plugin)._api_version = NBDKIT_API_VERSION; \ (plugin)._thread_model = THREAD_MODEL; \ return &(plugin); \ } leaves the user to call extern "C" { NBDKIT_REGISTER_PLUGIN(myplugin) } when they call it for nbdkit to pick it up. Was also hesitant to extern "C" around the other include files #include <stdarg.h> #include <stdint.h> Well I can _nearly_ get this to work, but when I try to compile a plugin with g++, I get: test-cxx-plugin.cpp:149:1: sorry, unimplemented: non-trivial designated initializers not supported Apparently you're not allowed to partially declare a struct in C++, so this isn't legal (or is legal but G++ doesn't support it, I'm not sure which): static struct nbdkit_plugin plugin = { name : "cxx", version : PACKAGE_VERSION, load : cxx_load, open : cxx_open, get_size : cxx_get_size, pread : cxx_pread, }; Created attachment 1246711 [details]
0001-Really-fix-C-support-in-the-nbdkit-plugin.h-header-f.patch
Interim patch (not working).
(In reply to Richard W.M. Jones from comment #3) > Apparently you're not allowed to partially declare a struct in C++, > so this isn't legal (or is legal but G++ doesn't support it, I'm not > sure which): > > static struct nbdkit_plugin plugin = { > > name : "cxx", It is a language shortcoming of C++. http://stackoverflow.com/questions/11516657/c-structure-initialization discusses various alternatives, none of them very satisfying for a POD type (which this is). You're pretty much limited to default initialization and per-member assignments, which makes it hard to create a pre-initialized static struct. Quoting from the link in comment 5, this might be viable: I found this way of doing it for global variables, that does not require to modify the original structure definition : struct address { int street_no; char *street_name; char *city; char *prov; char *postal_code; }; then declare the variable of a new type inherited from the original struct type and use the constructor for fields initialisation : struct temp_address : address { temp_address() { city = "Hamilton"; prov = "Ontario"; } } temp_address; OK I posted a proper fix (unfortunately rather complex): https://www.redhat.com/archives/libguestfs/2017-February/msg00004.html (In reply to Eric Blake from comment #6) > Quoting from the link in comment 5, this might be viable: > > I found this way of doing it for global variables, that does not require to > modify the original structure definition : > > struct address { > int street_no; > char *street_name; > char *city; > char *prov; > char *postal_code; > }; > > then declare the variable of a new type inherited from the original struct > type and use the constructor for fields initialisation : > > struct temp_address : address { temp_address() { > city = "Hamilton"; > prov = "Ontario"; > } } temp_address; Hmm OK, I'll see if that works ... The way I did it in the patch above was the use __attribute__((constructor)) to include a function that would run before plugin_init was called. you can also use a static initializer function example of anon namespace initializer namespace { nbdkit_plugin create_my_plugin() { nbdkit_plugin plugin = nbdkit_plugin(); plugin.name = plugin_name; plugin.load = plugin_load; plugin.unload = plugin_unload; plugin.config = plugin_config; plugin.config_complete = plugin_config_complete; plugin.config_help = plugin_config_help; plugin.open = plugin_open; plugin.close = plugin_close; plugin.get_size = plugin_get_size; plugin.pread = plugin_pread; plugin.pwrite = plugin_pwrite; plugin.flush = plugin_flush; plugin.trim = plugin_trim; return plugin; } } static struct nbdkit_plugin = create_my_plugin(); example of c++11 lambda initializer static nbdkit_plugin plugin = []() -> nbdkit_plugin { nbdkit_plugin plugin = nbdkit_plugin(); plugin.name = plugin_name; plugin.load = plugin_load; plugin.unload = plugin_unload; plugin.config = plugin_config; plugin.config_complete = plugin_config_complete; plugin.config_help = plugin_config_help; plugin.open = plugin_open; plugin.close = plugin_close; plugin.get_size = plugin_get_size; plugin.pread = plugin_pread; plugin.pwrite = plugin_pwrite; plugin.flush = plugin_flush; plugin.trim = plugin_trim; return plugin; }(); Yeah I guess comment 9 is better. Patch v3 posted: https://www.redhat.com/archives/libguestfs/2017-February/msg00009.html OK I pushed the v3 patch upstream. |