#Raw pointers content overwriting

26 messages · Page 1 of 1 (latest)

eager rock
#

Hello, I got stuck in solving one problem. I need a DLL for interop and Rust function can have only this syntax:

pub extern "C" fn vfp_test12(
    input: *mut c_char,
    output: *mut c_char
) -> *const c_char {
}```
Output parameter is C char* pointer and I need to change pointing data to sort of string.
I found this unsafe solution:

unsafe {
let output_value = std::ffi::CString::new("ABCD123456789").unwrap();
std::ptr::copy_nonoverlapping(output_value.as_ptr(), output as *mut i8, output_value.as_bytes().len() + 1);
}```
Is it good solution or crap?
I cannot use *mut *mut c_char for output, because DLL consument cannot bind this kind of syntax...

unborn saffron
#

i'm not following why you can't use that syntax

#

it's not that exotic

#

Well the obvious downside is what if the *mut c_char points into static memory. or if it is shorter than your output value

eager rock
#

Yes, size of memory is problem, I know that. But can I do it another way with this *mut c_char syntax? I think everything depends on how is char* allocated in memory and this is exactly the only solution...

unborn saffron
#

you use *mut *mut c_char

#

I remain unconvinced that you cannot do this

#

So is this thing the return value of this function or do you actually need to use an out parameter? I'm confused

eager rock
#

No, I cannot use *mut *mut c_char. I thought it can be used and helpful, but DLL consumer cannot bind this parameter.
This is all about using function parameter for returning some other value, that cannot be a part of standard function return.

hollow veldt
# eager rock Hello, I got stuck in solving one problem. I need a **DLL for interop** and Rust...

cannot bind this kind of syntax...
Do you mean the consumer doesn't understand how to deal with double pointers? i.e. they wouldn't understand char** in C either? Because what you said calls attention to the syntax, as if to imply that the problem is what the source code looks like as opposed to what the source code means.

As for the answer: You don't really need to allocate a CString: the following is just as valid:

#[unsafe(no_mangle)]
pub unsafe extern "C" fn vfp_test12(input: *mut c_char, output: *mut c_char) -> *const c_char {
  unsafe {
    let bytes = b"ABCD12345789\0";
    ptr::copy_nonoverlapping(bytes.as_ptr().cast::<c_char>(), output, bytes.len())
    //idk, pick something to return
  }
}
unborn saffron
#

And who says that this is the correct function signature?

eager rock
#

Thanks a lot for reply. Consumer of DLL means here Visual FoxPro, and it cannot deal with double pointers as far as I am able to find out. Rust and Visual FoxPro are from very different time, so I tried to convert issue through C-lang, where it's char**.
My function signature works and is bindable and used previously...

unborn saffron
#

char** in C is ubiquitous and has been used since the very start. If you told a bunch of C programmers "I can't use char** in a dll" they'd look at you weirdly

#

Is there some documentation somewhere about foxpro and C interop?

eager rock
#

DLL is consumed in Visual FoxPro and char** feature from C-lang does not have relative in Visual FoxPro. I asked some people for VisualFoxPro interop, they know C-lang, and they told "don't use char**, it needs to use some alloc stuff in Visual FoxPro and you are going to thin ice...

#

Visual FoxPro is 20 yrs dead...

unborn saffron
#

I'm starting to wonder what a foxpro STRING type actually is

#

Is it basically a *mut [c_char; 255]?

eager rock
#

Yes, I think it is.

unborn saffron
#

Then i think what T-Dark wrote is your best option

eager rock
#

Thanks for help both! 🙂 👍

unborn saffron
#

actually no, I think it's not always that long. im looking at snippets like ```

DECLARE INTEGER GetActiveWindow IN win32api

DECLARE INTEGER GetWindowText IN win32api Integer, String, Integer

hwnd = GetActiveWindow()

buf = space(100)

=GetWindowText(hwnd,@buf,len(buf))

?buf ``` so probably have to pass `pointer, length` and check that your string fits in that length
eager rock
#

And if I do not send length, the only fail is that my return string will be cropped to 100 size?

#

Because I am sending SPACE(256) and trim it with ALLTRIM()

unborn saffron
#

well this is an example