I have a managed C++ wrapper class for a non-managed C library. I came across an issue where it seems that the pointer I am sending from my managed C++ class is not pointing to the same memory location which is used by the non-managed C code library method.
MyNonManagedType* dataPointer;
getDataFromNonmanagedCLibrary(dataPointer);
// this gives me junk data, where field should be a char array
String^ myFieldValue = gcnew String(dataPointer->field);
Is it possible that the dataPointer is not pointing to the same address used by the C library? Or maybe there is some kind of marshal method I need to use for this, or other pitfalls I may be missing?
If the pointer is not managed, given the code you have shown, there is no way for a C function to do anything with the uninitialized pointer except either:
Check it for NULL, and if so, do nothing with it, or
Use the address passed, and disaster happens.
You are passing the pointer by value, and passing by value means that the function will be using a local copy of the parameter that is passed, thus you see no changes when the function returns. The function cannot set the pointer and have those changes reflect back to the caller the way it stands now.
Since we're talking about a C interface, you should change the C interface to this:
void getDataFromNonmanagedCLibrary(MyNonManagedType**);
A pointer to the pointer is passed. Since we want to change the value passed to the function and have it reflect back to the caller, a pointer to the value is passed. Since the value just happens to be a pointer, we pass a pointer to the pointer.
Then you rewrite getDataFromNonmanagedCLibrary to initialize the pointer by dereferencing it:
void getDataFromNonmanagedCLibrary(MyNonManagedType** ptr)
{
*ptr = <the_address_you_expected_on_return>;
}
Then on the client side:
MyNonManagedType* dataPointer;
getDataFromNonmanagedCLibrary(&dataPointer);
Note that the address of the pointer is passed, no different than if you wanted to have a function change a non-pointer variable by passing the variable's address.
Related
I've got a piece of code in which I use boost::unsafe_any_cast<void*>(&boost::any anyInstance) to obtain the content pointer of a boost::any object.
The code is this below:
boost::any staticResult; //contains a private pointer called content
f(staticResult); //makes the content pointer a null pointer
void* voidStaticResult = boost::unsafe_any_cast<void*>(&staticResult);
Unfortunately, debugging, I see that the content pointer in staticResult is NULL (0x00000000) while voidStaticResult is 0x00000004.
(Apparently there's no reason for that. Have you got any ideas?)
EDIT: The function f() calls a dll creating an instance of an object. The instance is pointed by the content pointer of staticResult. I need to pass the pointer to another function, but it seems to me there's no easy way to "cast" boost::any to a pointer to the instantiated class. Any other solution would be great.
Probably unsafe any cast is only valid for non empty any's. It is unsafe and unchecked.
Any is often implemented as a pointer at a block of memory where there is a vtable followed by the object instance. So to get a pointer to the object, you add sizeof(vtable ptr) to the any internal pointer, 4 on your build.
The setup is I have an object and below that object is a secret pointer.
This pointer points to an object of the same class but a different object than the one above it.
I have a function that takes in the top object and uses pointer arithmetic to get the pointer that is below it.
Then inside this function I want to modify the value of the object the secret pointer is pointing to.
In debug I can see the value is being modified just fine in the function but once the function returns the value is not preserved.
I'm beyond confused why.
Any ideas?
Also I own all the memory that these objects and pointers are being created in so I don't think any heap issues should occur as I'm doing my own little memory manager for fun.
I"m thinking the issue is related to me using reinterpret_cast, if I"m right what would be a solution/alternative, and why is this the issue?
void doWork(Obj* pObj) {
// Get address of the object the pointer is pointing to
unsigned char* position = reinterpret_cast<unsigned char*>(pObj);
// 16 Bytes below the object is a secret pointer
position += (sizeof(Obj) + 16);
// Retrieve the secret pointer
Obj* secretObj = reinterpret_cast<Obj*>(position);
// Modify a value in that secret object
secretObj->value += 1;
}
I have tried the suggestions of passing the pointer in by reference and still had no luck.
I'm confused why the way the pointer is passed in would even matter at all honestly as I'm only using that pointer to get the address to use as base then I go and create a new pointer using reinterpret cast with that (address + sizeof(Obj)) and do my work on that newly created pointer.
It's because that you are passing pointer to a pointer.
The address of an address, any changes will be held locally in the scope of function only.
For solving this you should pass the pointer with reference.
void doWork(Obj* &pObj)
This should work.
The (&(*pObj)) is redundant. You are taking the address of an object you just dereferenced. Surely (&(*pObj)) == pObj?
The most likely problem is your offset calculation. Your calculation adds the size of Obj and 16. We cannot tell from your example if this is correct because you don"t give us details of Obj or how the secret pointer is defined. If this calculation is wrong, then the update to value will appear to have worked in your function but you have changed the wrong bytes so it is not seen correctly outside the function.
I am currently trying to call a sqlite3 library function, and it expects me to pass it a sqlite3**.
Here is my current code. I have one working part, and one part that gives me an error:
sqlite3 *sqlite = m_db.get();
if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite))
{
}
if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &(m_db.get()) ))
{
}
My m_db field looks like this:
std::unique_ptr<sqlite3> m_db = nullptr;
Of the two examples I displayed, the first one is working perfectly fine. However, the second gives me this error. Note that this is coming from the &(m_db.get()) part:
“Address expression must be an lvalue or a function designator”
I read up a little bit about lvalues and rvalues, but I can't seem to figure out why this syntax would not be possible. As far as I understood by now, the problem is that the return value of the .get() operation is merely only a temporary expression result, and therefore doesn't have an identifiable location in memory where I could fetch the adress from.
There has to be a way to achieve this in one statement, I guess.
Can anyone explain to me why this is not working and how I can possibly fix it?
The & operator can only be used with an lvalue (or with a qualified id when making pointers-to-member). The expression m_db.get() is an rvalue because it returns a pointer by value, not by reference, so you cannot take its address.
unique_ptr provides no method for accessing the underlying pointer as a reference, you'll need to store a copy somewhere as in your first example.
A smart pointer stores a pointer and returns it on get. What you want to do here is the opposite: you get a pointer from sqlite3_open and want to store it in a smart pointer. So you would do something like
sqlite3* db = nullptr;
sqlite3_open(..., &db);
m_db.reset(db);
As the main feature of the unique_ptr is to delete the contained pointer in its destructor, I'm not sure if it makes sense to use it here. As far as I understand it, you are supposed to call sqlite3_close on the returned pointer, not delete it.
There has to be a way to achieve this in one statement, I guess.
I'm not quite sure about that; the point about temporary values really might be that it takes a statement to get a permanent one.
Also, you're messing with the semantics of the smart pointer, which you shouldn't do – .get should really not be used here.
Soooo, what I'd do is rely on C++ scoping here, and don't care about the fact that I declare a "normal" pointer first to make a smart pointer later.
your_class::initialize_db() {
sqlite3 *sqlite;
int retval = sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite);
if(retval == SQLITE_OK)
m_db = std::unique_ptr<sqlite3>(sqlite);
}
An lvalue is basically something which can appear on the left hand side of the assignment operator. So the error says that you can only retrieve the address of something which can be assigned to, or a function. It would have worked if you had member access to the sqlite3* pointer inside the unique_ptr, but you don't, and for good reason.
More to the point, you should not use a smart pointer in this case. If sqlite3_open requires an sqlite3** argument, then it means that the function will provide a value for the sqlite3* pointer. Basically it is an out parameter form C# or other such languages. It would have been clearer for it to be provided as a function result, but that was taken away by the result code. This is all well and good, but the smart pointer wants to have control over this value. You set the value once at initialization, but after that, the smart pointer takes care of it. And it needs to do this in order to maintain its constraints: uniqueness of ownership, deallocation when the pointer itself goes out-of-scope etc. If you basically go and overwrite the sqlite3* pointer inside, then that can't happen anymore, because the smart pointer has no way of intercepting the overwrite and deallocating the object it is currently using.
A pointer that is passed-in-by-reference. Why? aren't pointers just references anyways? What's really happening to this parameter?
void someFunc(MyPtr*& Object)
{
}
Simply speaking, it gives you the ability to change the pointer itself: it can be changed to point to another location in the function.
And the change will be reflected outside.
It enable you to:
void someFunc(MyPtr*& Object)
{
//Modify what Object is pointing to
Object=&old_Object;
//You can also allocate memory, depending on your requirements
Object=new MyPtr;
//Modify the variable Object points to
*Object=another_object;
}
Other's will have to vote to verify this cause I'm a bit rusty on my C++ but I believe the idea here is you'd pass in a pointer by reference, that is instead of creating a new space to store the pointer itself you use a reference to the pointer so if you were to modify the pointer not just the value it would be modified after returning from the function, whereas otherwise all you could do is modify the value at position passed in. Hope that makes sense.
The difference to passing just a pointer is that if the pointer is changed (Object = x) then this change will be seen by the calling function. You could achieve the same when you pass MyPtr** Object and dereference the pointer *Object = x;. With the second approach you could pass NULL to the function. This is not possible for references.
You are not quite right. The pointer content is passed by reference but the pointer itself is still passed by value, i.e. reassinging it to some other pointer will not be reflected upon the exit from the method because the pointer will be set to point to the same memory block as before the call. Think of it as a simple int variable. However with &* or ** you can reassign the pointer and that will be visible outside the scope of this method.
Why?
For the same reason that you would pass in anything else by reference.
aren't pointers just references anyways?
Dear god, no. Not even remotely the same thing. Look, you can try to build a mental model of a reference by starting with a pointer, but by the time you've fixed up all the differences, you have a horrible illogical mess.
References are a much simpler and more intuitive concept, and there are only "historical reasons" for trying to understand pointers before them. Modern C++ uses raw pointers only rarely, and treats them as an implementation detail as much as possible.
A reference is another name for an already-existing thing. That's it. When used as a function parameter, they thus allow the called function to refer to the caller's data.
It also means the pointer can be 0 (NULL) which can having meaning to the method. A reference must always be valid and cannot be made 'nothing'
I'm looking through an API written in C++ and I'm confused as to what the following parameter type means:
void*& data
Does that mean the user would pass in a reference to a void pointer? If that's true, what's the point? I mean void* is already indirected so why would you ever want to redirect it again?
void * means pass-by-pointer in C++, meaning you pass in a pointer, but it's actually a copy of the pointer. If you modified this pointer in your function, like changing its address, it is not reflected in the pointer you passed in.
Combining that with pass by reference, void *& means you are passing an alias of the original pointer to this function. If you modified it, like changing its address, it will be reflected in the original pointer.
It's tough to say without seeing it's use, but you point out that a reference is a level of indirection. Would you find it weird if it was a pointer to a pointer? Those are quite common - in fact you deal with them when accepting command line arguments and get pointers to char pointers. Another example would be if you were making a hash map using buckets, and wanted to be able to return the pointer to the pointer that started the bucket.
The point being is that sometimes you need multiple levels of indirection. It is true that mixing pointers and references can be quirky, but there are good reasons for it. One common reason is the need for C++ code to interact with C apis. A lot of POSIX system calls require void pointers that get passed in and then changed, so the C++ function in question may be acting as a wrapper around that.
But be careful to not return reference to local void*.
Don't do something like this:
void*& f()
{
int* a=new int(10);
void* x=(void*)a;
return x;
}