PInvoke was used to pass the following structure from VB.net to unmanaged C when the app starts up. All the values are passed in correctly as I step through the code. Inside the called C method I save a the ptr to the passed in struct.
<StructLayout(LayoutKind.Sequential)>
Structure teststruct
<MarshalAs(UnmanagedType.I2)> Public TestData As Short
<MarshalAs(UnmanagedType.I2)> Public TestData2 As Short
<MarshalAs(UnmanagedType.I2)> Public TestData3 As Short
<MarshalAs(UnmanagedType.ByValArray, ArraySubType:=UnmanagedType.I2, SizeConst:=256)> Public TestData4() As Short
End Structure
//Matching C struct
struct teststruct
{
short TestData;
short TestData2;
short TestData3;
short TestData4[256];
};
//The method in C that saves ptr to the struct that is passed in (Worked with VB6)
struct teststruct *VCstruct;
void DllCallbackFunc(struct teststruct *VBStruct)
{
VCstruct = VBStruct;
}
After I save the ptr to the passed in struct, the ptr be invalid as soon as the function returns to VB.net.
I suspect that the marshaller allocated memory is freed after the callback function returns
Is there a way to tell the marshaller to NOT deallocate the memory it allocated during marshaling?
Appreciate any comments.
Thanks
The pointer that the p/invoke marshaler passes to the unmanaged code is valid only until the unmanaged function returns. You have two options, as I see it:
Have the calling code pass a pointer that remains valid for as long as the unmanaged code retains a copy of the pointer. That will require a signature change to pass an IntPtr. And calls to Marshal.AllocHGlobal and Marshal.StructureToPtr.
Have the unmanaged code take a copy of the structure rather than a copy of the address of the structure.
The latter option is more commonly chosen.
Related
I am playing with LabVIEW 2019 64bit and Rust 1.64, but LabVIEW crashed on a very simple code.
What I am trying to do is passing a Hello from Rust string to LabVIEW and then deallocate it back in Rust.
use libc::c_char;
use std::ffi::CString;
#[no_mangle]
pub extern "cdecl" fn hello() -> *const c_char {
CString::new("Hello from Rust")
.expect("failed to create c string")
.into_raw()
}
#[no_mangle]
pub extern "cdecl" fn bye(s: *mut c_char) {
unsafe {drop(CString::from_raw(s));}
}
LabView can display correct string but freezes and then crashed when calling bye(s).
However, if I manually disable bye(s) function call, everything is all right, but it violates Rust suggestion:
alloc::ffi::c_str::CString
pub fn into_raw(self) -> *mut c_char
Consumes the CString and transfers ownership of the string to a C caller.
The pointer which this function returns must be returned to Rust and reconstituted using CString::from_raw to be properly deallocated. Specifically, one should not use the standard C free() function to deallocate this string.
Failure to call CString::from_raw will lead to a memory leak.
What is the correct way to perform this simple task?
Thanks to #srm , LabVIEW is working fine now. Here is the working block diagram:
The problem you have is that LabVIEW is receiving the C string and converting it to an L string (very different memory signature). The pink wire in LabVIEW is a pointer to a char[N] where N is the length of the string + 4 bytes... the first 4 bytes of the array is the length of the string. It's similar to a Pascal string but with 4 byte length instead of 1 byte length. The data structure that LV is consuming isn't the same one that you're passing out to bye(). You never get your hands on that raw pointer... with your current Call Library setup. So let's change your setup.
Background: Remember that LabVIEW has, essentially, the same rules for memory management that Rust has -- namely that LabVIEW knows to allocate and deallocate data on a fixed schedule, and it expects to be in control of the memory management. LabVIEW does NOT have a garbage collector. It analyzes the dataflow and makes decisions about where to deterministically release data. But it also doesn't assume that data goes out of scope -- there is no "scope" for LabVIEW VIs. Ideally for LabVIEW, that pink wire will remain allocated for the next call of the VI on the presumption that the next call will also need the same string buffer.
Solution: If you want Rust to allocate the string, you need to tell LabVIEW that what is being returned is just an address. So tell LabVIEW the return type is a pointer-size integer, not a string. Also return the length of the string.
On the diagram, call your hello() function to return the integer and the length of the string. Then have another Call Library function to invoke the built-in function MoveBlock.
https://www.ni.com/docs/en-US/bundle/labview/page/lvexcode/moveblock.html
Set the library name to "LabVIEW" -- no file extension. Then make the first parameter be your pointer-sized integer. The second parameter is a LabVIEW array of bytes that you call Initialize Array and init to N characters where N is the length of the string -- configure the Call Library node to do arrays by pointer. The third parameter is the length of the string.
MoveBlock will copy the bytes out of the C string allocated by Rust into the L string allocated by LabVIEW. You can then pass the pointer-sized integer into your bye() function.
For an example, let's take this struct
var input struct {
Title *string `json:"title"`
Year *int32 `json:"year"`
Runtime *data.Runtime `json:"runtime"`
Genres []string `json:"genres"`
}
I get the purpose of using pointer values like this when decoding JSON values. But my question is when we store a pointer to a string in the input field (for an ex) input.Title, Where does the underlying value for that pointer is stored? It's simply stored in some memory address randomly? or what actually is going on behind the scenes
The JSON decoder calls reflect.New to get a pointer to a new empty string value. The decoder sets the value to the decoded string and sets the struct field to the pointer.
The reflect.New function calls a private runtime function to allocate heap memory for the value. The function returns a pointer to that memory.
I have code like this:
struct MyStruct {
immutable int id;
immutable int value;
this() #disable;
this(immutable int pId) {
id = pId;
value = getValueById(id);
}
}
void main() {
MyStruct structs = new MyStruct[](256); // No default initializer
foreach(ulong id, MyStruct struct_; structs) {
structs[id] = MyStruct(id); // Cannot edit immutable members
}
}
I know I could just initialize a dynamic array and add to it, but I'm interested to see if there is a more efficient way of doing this. I'm mostly concerned about how it'll have to reallocate every time while it really knows how much memory it needs in advance.
Simplest solution is to use the dynamic array and call the .reserve method before doing any appends. Then it will preallocate the space and future appends will be cheap.
void main() {
MyStruct[] structs;
structs.reserve(256); // prealloc memory
foreach(id; 0 .. 256)
structs ~= MyStruct(id); // won't reallocate
}
That's how I'd do it with dynamic arrays, writing to individual members I don't think will ever work with immutability involved like this.
BTW if you wanted a static array, calling reserve won't work, but you can explicitly initialize it.... to void. That'll leave the memory completely random, but since you explicitly requested it, the disabled default constructor won't stop you. (BTW this is prohibited in #safe functions) But in this case, those immutable members will leave it garbage forever unless you cast away immutability to prepare it soo.. not really workable, just a nice thing to know if you ever need it in the future.
I have a class, user, which stores objects of another class, foo, in a vector. I am trying to figure out what is the best way of creating objects of class foo and store them in vector of class user.
class Foo {
public:
Foo();
Foo(std::string str);
std::string name;
Foo* GiveMeFoo(std::string arg);
};
Foo::Foo() {}
Foo::Foo(std::string args):name(args) {}
Foo* Foo::GiveMeFoo(std::string arg) { return new Foo(arg) };
class User {
public:
vector < Foo *> v;
vector < Foo> v2;
vector < Foo*> v3;
void start();
};
void User::start()
{
const int SIZE = 3;
string a[SIZE] = {"one","two","three"};
for (int i = 0; i < SIZE; i++ ){
//method1
Foo *f = new Foo();
f->name = a[i];
v.push_back(f);
//method2
Foo f2;
f2.name = a[j];
v2.push_back(f2);
//method3
Foo f3;
v3.push_back(f3.GiveMeFoo(a[k]));
}
}
Question1: Between methods 1, 2 and 3 is there a preferred way of doing things? Is there a better way of creating objects of remote class locally and storing them in a vector?
Question 2: Are all the objects that are getting stored in the vectors of class User persistent (e.g. even if the foo object goes away, once I have pushed those objects onto vector in user, then copies of those foo objects will be persistently stored in the vector, correct?
Unless there are other considerations, method 2 is preferred.
Vectors (and other STL containers) store copies of the argument to push_back().
This means that for method 1, you are allocating a Foo on the heap and then storing a pointer to it in the vector. If the User object is destroyed, the Foo objects will leak unless you take steps to delete them (like delete them in the User destructor).
For method 2, you have allocated a Foo on the stack. This object is then copied into the vector. When start() exits, the original Foo is destroyed but the copy survives in the vector. If the User object is destroyed then so is the vector and consequently the Foo.
For method 3, you have allocated a Foo on the stack. You then call GiveMeFoo() on it which allocates another Foo on the heap and then returns a pointer to it. This pointer is then copied into the vector. When start() exits, the original Foo will be destroyed but the heap allocated object will survive. If the User object is destroyed then so is the vector but the heap allocated Foo survives and leaks unless you destroy it manually in the destructor of User.
If you need to store a pointer to an object rather than a copy then you are better off using std::tr1::shared_ptr (if your compiler supports it) to manage the lifetime of the Foo objects.
In case it helps someone, as of C++11, std::vector (along with some of the other STL containers) now have the ability to "emplace" an instance into the collection. This has the advantage of avoiding a possible extra duplicate object or copy.
For the example above, code like this can be used instead:
v.emplace_back(a[i]);
More information: std::vector::emplace_back
What difference there is when you access to another struct by value or by a pointer?
When should be used each one of them?
type foo_ struct {
st uint8
nd uint8
}
type bar struct {
rd uint8
foo foo_
}
type barP struct {
rd uint8
foo *foo_
}
If you declare or allocate a variable of type bar, you reserve and initialize to zero memory for both rd uint8 and foo foo_. There is always one variable of type foo_ embedded in a variable of type bar.
var b bar // declare b
If you declare or allocate a variable of type barP, you reserve and initialize to zero memory for both rd uint8 and foo *foo_. A zero value pointer is a nil pointer. No variable of type foo_ is allocated; you must do that separately. There is either zero (foo == nil) or one variable of type foo_ pointed to by a variable of type barP. A variable of type barP may point to the same variable of type foo_ as other variables of type barP, sharing the same copy of the variable of type foo_. A change to a shared copy is seen by all variables that point to it.
var bp barP // declare bp
bp.foo = new(foo_) // allocate bp.foo
Which one to use depends on the properties of type bar versus type barP. Which type more closely reflects the problem that you are trying to solve?
For example, consider this invoice problem. We always have a billing address; we are always going to ask for our money. However, we often ship to the billing address, but not always. If the shipping address is nil, use the billing address. Otherwise, use a separate shipping address. We have two warehouses, and we always ship from one or the other. We can share the two warehouse locations. Since we don't send an invoice until the order is shipped from the warehouse, the warehouse location will never be nil.
type address struct {
street string
city string
}
type warehouse struct {
address string
}
type invoice struct {
name string
billing address
shipping *address
warehouse *warehouse
}
The answer is largely independent of language - the equivalent in C has the same issues.
When you have an embedded value (as in bar), then your structure is big enough to hold the complete sub-structure and the other part.
When you have a pointer to a value (as in barP), then a number of structures of type barP may share the same foo. When any of the barP modifies a part of the foo it points to, it affects all the other barP structures that point to the same place. Also, as the commentary suggests, you have to manage two separate objects - the barP and the foo as against one with the plain bar type.
In some languages, you would have to worry about dangling pointers and uninitialized values etc; Go is garbage collected and generally more type-safe than other languages.
So, use a pointer when you want multiple barP objects to share the same foo object; otherwise, use an explicit member object, rather than a pointer to an object.
The Golang FAQ now summarizes the difference between:
func (s *MyStruct) pointerMethod() { } // method on pointer
func (s MyStruct) valueMethod() { } // method on value
First, and most important, does the method need to modify the receiver?
If it does, the receiver must be a pointer. (Slices and maps are reference types, so their story is a little more subtle, but for instance to change the length of a slice in a method the receiver must still be a pointer.)
In the examples above, if pointerMethod modifies the fields of s, the caller will see those changes, but valueMethod is called with a copy of the caller's argument (that's the definition of passing a value), so changes it makes will be invisible to the caller.
By the way, pointer receivers are identical to the situation in Java, although in Java the pointers are hidden under the covers; it's Go's value receivers that are unusual.
Second is the consideration of efficiency. If the receiver is large, a big struct for instance, it will be much cheaper to use a pointer receiver.
(This efficiency point is also illustrated in "Memory, variables in memory, and pointers ")
Next is consistency. If some of the methods of the type must have pointer receivers, the rest should too, so the method set is consistent regardless of how the type is used. See the section on method sets for details.