I have a COM object named factory (IFactory), and it has several methods like
virtual HRESULT STDMETHODCALLTYPE CreateDatabase(IDatabase** Result) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateProcessor(IProcessor** Result) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateDocument(IDocument** Result) = 0;
.....
when I need create a IDocument, I need to do this:
IDocument* doc = nullptr;
factory->CreateDocument(&doc);
// some code here;
doc.Release();
So I want to create a common function to do this and generate a shared_ptr, so taht I do not need to release it manually.
I created a function like this:
template <typename T, typename K>
shared_ptr<T> create_new(K* p, HRESULT (K::*member)(T**)) {
T* pointer = nullptr;
(void)p->*member(&pointer);
shared_ptr<T> result(pointer, [=](T* o) {
o->Release();
});
return result;
}
This way, when I need create a new IDocument I just need:
auto doc = create_new(factory, &IFactory::CreateDocument);
// do not need release it manually
but this does not work, because the compiler needs more information to instantiate the template, so I use
auto doc = create_new(factory, (HRESULT (IFactory::*)(IDocument**))&IFactory::CreateDocument);
this way seems correct, but when I compile my code, the compiler stops at
(void)p->*member(&pointer);
and says:
must use '.*' or '->*' to call pointer-to-member function in 'member (...)', e.g. '(... ->* member) (...)'
In instantiation of 'std::shared_ptr<_Tp1> create_new(K*, HRESULT (K::*)(T**)) [with T = IDocument; K = IFactory; HRESULT = long int]'
Could someone help me figure this out?
Compiler is MinGW-w64 GCC 4.8.5, but I tried GCC 5.3.0, with the same output.
First off, function calls bind tighter than member pointer dereference, so you need these parentheses:
(p->*member)(&pointer);
(Add cast to void as you prefer).
Second, you can improve your call syntax by specifying the argument for T explicitly; you should then not need the horrible cast:
auto doc = create_new<IDocument>(factory, &IFactory::CreateDocument);
Related
I want to write a class that makes use of numerical quadrature. The quadrature order defines the size of some containers that I will use. I would like to make a type alias for such containers and it has to depend on the quadrature order.
The following code shows my trials. It feels suboptimal in the sense that I have to repeat the order in the type alias definition:
#include <array>
class Quadrature
{
public:
static constexpr unsigned int getOrder()
{
return 3;
}
// This line doesn't compile!
//
// using WeightsContainer = std::array<double, getOrder()>;
//
// g++ says "error: 'static constexpr unsigned int Quadrature::getOrder()'
// called in a constant expression before its definition is complete"
// This line compiles, but repeats the order. :-(
using WeightsContainer = std::array<double, 3>;
private:
WeightsContainer container;
};
One solution that I have found is introducing a template parameter Order. But actually I wanted to determine the quadrature order and introducing the template parameter would make it variable.
Is there a possibility to make the order a compile-time constant and use it within my type alias definition?
Edit:
For completeness, I could of course use a preprocessor define. But that feels old-fashioned. :-)
Edit 2:
Okay, I have found another possibility. I could add a function outside the class scope like this:
constexpr unsigned int order()
{
return 3;
}
But that feels wrong, because this is a property of the class and therefore should be within class scope!
One thing you can do is to move the value into a member variable:
class Quadrature
{
private:
static constexpr unsigned int _order = 3;
public:
static constexpr unsigned int getOrder()
{
return _order;
}
using WeightsContainer = std::array<double, _order>;
// ...
};
If you need more complicated computations instead of just return 3, under C++17 you can use a lambda as #Quentin mentioned:
class Quadrature
{
public:
static constexpr auto getOrder = []()
{
return ...;
};
using WeightsContainer = std::array<double, getOrder()>;
// ...
};
Otherwise, you will need to pull the function outside of class scope for reasons mentioned here.
Suppose there is a class with a few data members, such as this:
struct s {
char c;
int i;
};
If I need a const-pointer to a member, it's simple enough:
auto s::* const ptr = &s::c;
If I try to create a static member of the same type, some weird things start happening...
For instance, this segfaulted the compiler (gcc 4.9.3):
struct s {
char c;
int i;
static auto s::* const static_ptr = &s::c;
};
// internal compiler error: Segmentation fault
// static auto s::* const static_ptr = &s::c;
// ^
Using it as a static member of a different class at least finishes compiling:
struct t {
static auto s::* const static_ptr = &s::c;
};
// error: 'constexpr' needed for in-class initialization of static data member 'char s::* const t::static_ptr' of non-integral type [-fpermissive]
// static auto s::* const static_ptr = &s::c;
// ^
That last error I don't understand, isn't &s::c a constexpr?
I do have a way to make it work, eg:
// also works with `struct s` this way, `struct t` is not needed for this
struct t {
static char s::* const static_ptr;
};
char s::* const t::static_ptr = &s::c;
But for several reasons this is undesirable:
auto cannot be used except in the definition, if it is initialized outside the class then the type must be declared.
Declaring the type explicitly means either repeating the type or repeating the member name (as decltype(s::c)) - more places to maintain the same name = more mistakes possible.
The above is even more of a nuisance with specialized class templates, where for each specialization this would need to be done inside and outside the class.
From this I have a two part question.
1. Why isn't &s::c a constexpr? Is there a way to make it one?
2. Is there a way to specify a static member that is a fixed pointer to a member of another class, with the type automatically determined, without resorting to decltype?
I have tried this as a member of struct s and get the same error (constexpr needed):
static constexpr auto s::* const member_c () {
return &s::c;
}
So I'm at a loss as to what the compiler's issue is with this sort of syntax, it just doesn't make sense to me why a reference to a data member (not an instance member reference) is not a constant at compile time.
dlopen() is a C function used for dynamically loading shared libraries at runtime. The pattern, in case you're not familiar, is thus:
Call dlopen("libpath", flag) to get a void *handle to the library
Call dlsym(handle, "object_name") to get a void *object to the thing you want from the library
Do what you want with object
Call dlclose (handle) to unload the library.
This is, in C++, a perfect use-case for the so-called aliasing constructor of std::shared_ptr. The pattern becomes:
Construct a std::shared_ptr<void> handle from dlopen("libpath", flag) that will call dlclose() when its destructor is called
Construct a std::shared_ptr<void> object from handle and dlsym(handle, "object_name")
Now we can pass object wherever we want, and completely forget about handle; when object's destructor is called, whenever that happens to be, dlclose() will be called automagically
Brilliant pattern, and it works beautifully. One small problem, though. The pattern above requires a cast from void* to whatever_type_object_is*. If "object_name" refers to a function (which most of the time it does, considering the use-case), this is undefined behavior.
In C, there is a hack to get around this. From the dlopen man page:
// ...
void *handle;
double (*cosine)(double);
// ...
handle = dlopen("libm.so", RTLD_LAZY);
// ...
/* Writing: cosine = double (*)(double)) dlsym(handle, "cos");
would seem more natural, but the C99 standard leaves
casting from "void *" to a function pointer undefined.
The assignment used below is the POSIX.1-2003 (Technical
Corrigendum 1) workaround; see the Rationale for the
POSIX specification of dlsym(). */
*(void **) (&cosine) = dlsym(handle, "cos");
// ...
which obviously works just fine, in C. But is there an easy way to do this with std::shared_ptr?
The pattern above requires a cast from void* to whatever_type_object_is*. If "object_name" refers to a function (which most of the time it does, considering the use-case), this is undefined behavior.
Well this is not entirely true, at least in C++ it is just conditionally-supported.
5.2.10.8 says:
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning
of such a conversion is implementation-defined, except that if an implementation supports conversions in
both directions, converting a prvalue of one type to the other type and back, possibly with different cvqualification,
shall yield the original pointer value.
So assuming that what dlsym does internally is casting a function pointer to a void*, I believe that you are ok if you just cast it back to a function pointer.
Something like this?
struct dlib
{
public:
template<class T>
std::shared_ptr<T> sym(const char* name) const {
if (!handle) return {};
void* sym = dlsym(handle->get(), name);
if (!sym) return {};
return {reinterpret_cast<T*>(sym), handle};
}
// returns a smart pointer pointing at a function for name:
template<class Sig>
std::shared_ptr<Sig*> pfunc(const char* name) const {
if (!handle) return {};
void* sym = dlsym(handle->get(), name);
if (!sym) return {};
Sig* ret = 0;
// apparently approved hack to convert void* to function pointer
// in some silly compilers:
*reinterpret_cast<void**>(&ret) = sym;
return {ret, handle};
}
// returns a std::function<Sig> for a name:
template<class Sig>
std::function<Sig> function(const char* name) const {
// shared pointer to a function pointer:
auto pf = pfunc(name);
if (!pf) return {};
return [pf=std::move(pf)](auto&&...args)->decltype(auto){
return (*pf)(decltype(args)(args)...);
};
}
dlib() = default;
dlib(dlib const&)=default;
dlib(dlib &&)=default;
dlib& operator=(dlib const&)=default;
dlib& operator=(dlib &&)=default;
dlib(const char* name, int flag) {
void* h = dlopen(name, flag);
if (h)
{
// set handle to cleanup the dlopen:
handle=std::shared_ptr<void>(
h,
[](void* handle){
int r = dlclose(handle);
ASSERT(r==0);
}
);
}
}
explicit operator bool() const { return (bool)handle; }
private:
std::shared_ptr<void> handle;
};
I doubt that hack is needed. As #sbabbi noted, the round-trip to void* is conditionally supported. On a system using dlsym to return function pointers, it better be supported.
You can make a struct to have your pointer to function and handle to library:
template<typename T>
struct dlsymbol {
dlsymbol( const std::string &name, std::shared_ptr<void> handle ) :
m_handle( std::move( handle ) )
{
*(void **)(&m_func) = dlsym( handle.get(), name.c_str );
}
std::shared_ptr<void> m_handle;
T *m_func;
};
auto cosine = std::make_shared<dlsymbol<double(double)>>( "cos", handle );
auto d = cosine->m_func( 1.0 );
I did not compile it, but I think it is sufficient to show the idea.
It might seem obvious to some, but I was still wondering: is there no way to make the compiler deduce the lambda return type without actually calling it?
Of course you can auto retval = myLambda();, however I want sth like:
T_MY_LAMBDA_RETVAL retval;
...
retval = myLambda();
Why would I want that? Simple:
try {
auto retval = myLambda();
catch (exception e) {
...
}
// retval is undefined but I wonna have it!!! :)
typedef typename std::result_of<decltype(lambda)()>::type return_type;
deduces the return type of invoking lambda with 0 arguments.
As would:
typedef decltype( lambda() ) return_type;
Be careful about possible rvalue references.
To complete Yakk's answer
with:
auto myLambda = [&](int) { return 42; }; // Or any lambda
you may use
using T_MY_LAMBDA_RETVAL = std::result_of<decltype(myLambda)(int)>::type;
or
using T_MY_LAMBDA_RETVAL = decltype(myLambda(std::declval<int>()));
and then use it:
T_MY_LAMBDA_RETVAL retval;
try {
retval = myLambda(42);
catch (exception& e) {
// ...
}
// you may use retval which may be uninitialized.
A lambda expression creates a unique functor type that overloads operator(), this is what gets invoked when you call the lambda. We can make use of this fact to figure out the return type of the lambda expression.
template<typename T>
struct lambda_traits_helper; // undefined
// specialize for pointer to member function
template<typename T, typename Result, typename... Args>
struct lambda_traits_helper<Result(T::*)(Args...) const>
{
using result_type = Result;
};
template<typename Func>
struct lambda_traits
: lambda_traits_helper<decltype(&Func::operator())>
// instantiate helper trait with pointer to operator()
{};
Example usage:
auto lambda = []{ return 42; };
assert((std::is_same<int, lambda_traits<decltype(lambda)>::result_type>::value));
auto lambda = [](int a){ return std::to_string(a); };
assert((std::is_same<std::string, lambda_traits<decltype(lambda)>::result_type>::value));
Live demo
I have the following c++ function which I cannot alter (3rd-Party):
[c++]
int __stdcall TEST(wchar_t **xml, int &result_size)
{
// xml is instantiated here!
}
[c#]
class native
{
[DllImport("somedll.dll")]
public static extern int TEST(StringBuilder a, ref int size);
{
}
}
Example:
StringBuilder b = new StringBuilder();
int size = 0;
native.Test(b,ref size)
The stringbuilder object only contains first character . If I resize the object:
b.Length = size; The data is incorrect except first character.
Is this the correct way to pass wchar_t** from c++ to c#?
Regards,
John
The function would be p/invoked like this:
[DllImport(#"mylib.dll")]
static extern int TEST(out IntPtr xml);
I removed the size paramter since it is not needed since you can use a null-terminated string.
Call the function like this:
IntPtr xmlptr;
int retval = TEST(out xmlptr);
string xml = Marshal.PtrToStringUni(xmlptr);
// deallocate xmlptr somehow
The tricky bit is to deallocate the memory allocated on the native side. Either use a shared allocator, e.g. the COM allocator. Or export a deallocator from the native code.
Personally I'd re-design the interface to use COM BSTR. I'd have the C++ return a BSTR and on the managed side use [MarshalAs(UnmanagedType.BStr)]. Then the framework handles all the deallocation and marshalling for you.