www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can we use "ImportC" used yet?

reply rempas <rempas tutanota.com> writes:
Cause I can't find an option in the latest DMD release and 
because the ImportC 
[page](https://dlang.org/spec/importc.html#importing) seems to be 
incomplete (even saying it's under construct), I'm wondering if 
ImportC exists even as prototype but it's hidden or if it's not 
available at all. Anyone knows?
Oct 15 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Friday, 15 October 2021 at 18:39:10 UTC, rempas wrote:
 Cause I can't find an option in the latest DMD release and 
 because the ImportC 
 [page](https://dlang.org/spec/importc.html#importing) seems to 
 be incomplete (even saying it's under construct), I'm wondering 
 if ImportC exists even as prototype but it's hidden or if it's 
 not available at all. Anyone knows?
There's no option, you just use a normal import statement when the module is named .c instead of .d I say 'just' but typical C uses the C preprocessor and can't be imported as-is. Here's an example in three files: ```d // fstat.d void main() { import std.stdio : writeln; import sys_stat : stat_t, fstat; stat_t buf; writeln(fstat(0, &buf)); writeln(buf); } ``` ```c // sys_stat_wrapper.c #define __restrict restrict #include <sys/stat.h> typedef struct stat stat_t; ``` ```make fstat: fstat.d sys_stat.c dmd $< sys_stat.c: sys_stat_wrapper.c gcc -E -P $< > $ ``` this is importing sys_stat.c , making space on the stack for a stat_t (what's that?), calling fstat on fd 0, and then writing the output, which might look like ``` 0 stat(27, 11, 1, 8592, 1000, 5, 0, 34824, 0, 1024, 0, timespec(1634329152, 581807916), timespec(1634329152, 581807916), timespec(1634272061, 581807916), [0, 0, 0]) 9 ``` the d programmer did not have to carefully `extern (C)` an fstat function, nor define a struct, nor care about issues like an evil platform padding its struct with some bytes and overwriting the stack unless the d programmer accounts for that. This is all nice. But you still had to write those three lines of C, to smuggle `struct stat` into d and to suppress non-standard `__restrict`. And you still need to invoke the C preprocessor as a build step. The next inconvenient thing is: what about when you want a c `#define` in d? Say, fstat's potential errors. You have to smuggle those as well, and because the C preprocessor fights you, you have to not just stuff those people in a box but also prepare new names for them. (And if platforms vary in errors? More build system work.) ```c // sys_stat_wrapper.c, continued #include <errno.h> enum errors { ebadf = EBADF, eio = EIO, eoverflow = EOVERFLOW, }; ``` ```d // fstat.d, continued import sys_stat : errors, ebadf; writeln(ebadf); writeln(errors.eoverflow); } ``` Of course you can rename when importing as usual, or have a separate .d module that cleans this interface up where the C preprocessor can't interfere. For function-like `#defines`, perhaps you'll want to write a C function that uses it. In conclusion, ImportC exists and you can use it, and complications like smuggling structs are discussed in that page. If you're going to wrap a new C library especially, it can take on 99% the tedium for you. If you're going to burn down an importc-by-hand work that you have already and replace it with ImportC, it might be better to wait for dub and gdc to catch up. As annoying as it might be to have C constants in your code, they do compile with fewer build steps.
Oct 15 2021
next sibling parent jfondren <julian.fondren gmail.com> writes:
On Friday, 15 October 2021 at 20:45:35 UTC, jfondren wrote:
 ```
 0
 stat(27, 11, 1, 8592, 1000, 5, 0, 34824, 0, 1024, 0, 
 timespec(1634329152, 581807916), timespec(1634329152, 
 581807916), timespec(1634272061, 581807916), [0, 0, 0])
 9
 ```

 the d programmer did not have to carefully `extern (C)` an 
 fstat function, nor define a struct, nor care about issues like 
 an evil platform padding its struct with some bytes and 
 overwriting the stack unless the d programmer accounts for that.
Speaking of padding the struct, what's what `[0, 0, 0]` at the end of my stat() output? I hadn't noticed it before. ``` __syscall_slong_t __glibc_reserved[3]; ``` yeah, core.sys.posix.sys.stat doesn't account for that.
Oct 15 2021
prev sibling parent reply rempas <rempas tutanota.com> writes:
On Friday, 15 October 2021 at 20:45:35 UTC, jfondren wrote:
 There's no option, you just use a normal import statement when 
 the module is named .c instead of .d

 I say 'just' but typical C uses the C preprocessor and can't be 
 imported as-is.

 [ ... ]
First of all, I see you answering questions (not only mine) very often so thanks ;). Now, I tried to do what you said but I'm getting an error. Now I'm just give you the code so you can also check it (if you want of course) and see what's going on. Let's see: ``` // Filename: test.d import test_c; void main() { hello_world(); } // Filename: test_og.c #include <stdio.h> #include <stdlib.h> void hello_world() { puts("Hello world!!!"); } ``` After that, I'm using: `gcc -E -P test_og.c > test_c.c` to preprocess just like you shown and then I'm using the final command with DMD: `dmd test.d test_c.c` and I'm getting the following error message: ``` /usr/include/stdio.h(246): Error: found `__filename` when expecting `,` /usr/include/stdio.h(247): Error: found `__modes` when expecting `,` /usr/include/stdio.h(252): Error: found `__filename` when expecting `,` /usr/include/stdio.h(253): Error: found `__modes` when expecting `,` /usr/include/stdio.h(254): Error: found `__stream` when expecting `,` /usr/include/stdio.h(304): Error: found `__stream` when expecting `,` /usr/include/stdio.h(304): Error: found `__buf` when expecting `,` /usr/include/stdio.h(308): Error: found `__stream` when expecting `,` /usr/include/stdio.h(308): Error: found `__buf` when expecting `,` /usr/include/stdio.h(314): Error: found `__stream` when expecting `,` /usr/include/stdio.h(314): Error: found `__buf` when expecting `,` /usr/include/stdio.h(326): Error: found `__stream` when expecting `,` /usr/include/stdio.h(327): Error: found `__format` when expecting `,` /usr/include/stdio.h(332): Error: found `__format` when expecting `,` /usr/include/stdio.h(334): Error: found `__s` when expecting `,` /usr/include/stdio.h(335): Error: found `__format` when expecting `,` /usr/include/stdio.h(341): Error: found `__s` when expecting `,` /usr/include/stdio.h(341): Error: found `__format` when expecting `,` /usr/include/stdio.h(347): Error: found `__format` when expecting `,` /usr/include/stdio.h(349): Error: found `__s` when expecting `,` ``` Checking the actual source code, it seems like a parsing error. Any ideas?
 The next inconvenient thing is: what about when you want a c 
 `#define` in d? Say, fstat's potential errors. You have to 
 smuggle those as well, and because the C preprocessor fights 
 you, you have to not just stuff those people in a box but also 
 prepare new names for them. (And if platforms vary in errors? 
 More build system work.)

 ```c
 // sys_stat_wrapper.c, continued
 #include <errno.h>
 enum errors {
     ebadf = EBADF,
     eio = EIO,
     eoverflow = EOVERFLOW,
 };
 ```

 ```d
 // fstat.d, continued
     import sys_stat : errors, ebadf;
     writeln(ebadf);
     writeln(errors.eoverflow);
 }
 ```

 Of course you can rename when importing as usual, or have a 
 separate .d module that cleans this interface up where the C 
 preprocessor can't interfere.

 For function-like `#defines`, perhaps you'll want to write a C 
 function that uses it.

 In conclusion, ImportC exists and you can use it, and 
 complications like smuggling structs are discussed in that 
 page. If you're going to wrap a new C library especially, it 
 can take on 99% the tedium for you. If you're going to burn 
 down an importc-by-hand work that you have already and replace 
 it with ImportC, it might be better to wait for dub and gdc to 
 catch up. As annoying as it might be to have C constants in 
 your code, they do compile with fewer build steps.
Agree, having to do it manually will just be a pain in the ass...
Oct 15 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Saturday, 16 October 2021 at 06:39:46 UTC, rempas wrote:
 ```
 // Filename: test.d
 import test_c;

 void main() {
   hello_world();
 }

 // Filename: test_og.c
 #include <stdio.h>
 #include <stdlib.h>

 void hello_world() {
   puts("Hello world!!!");
 }
 ```

 After that, I'm using: `gcc -E -P test_og.c > test_c.c` to 
 preprocess just like you shown and then I'm using the final 
 command with DMD: `dmd test.d test_c.c` and I'm getting the 
 following error message:

 ```
 /usr/include/stdio.h(246): Error: found `__filename` when 
 expecting `,`
 ```
These are __restrict errors again, but then I get a bunch of others as well. This test_og.c works (while obviously breaking some bswap functions): ```c #define __restrict restrict #define __asm__ asm #define __extension__ #define __inline #define __builtin_bswap16 #define __builtin_bswap32 #define __builtin_bswap64 #include <stdio.h> #include <stdlib.h> void hello_world() { puts("Hello world!!!"); } ``` It would be less annoying to compile the original test_og.o with gcc and then link it in.
Oct 16 2021
parent reply rempas <rempas tutanota.com> writes:
On Saturday, 16 October 2021 at 07:09:16 UTC, jfondren wrote:
 This test_og.c works (while obviously breaking some bswap 
 functions):
I don't know if I should have known that but what is "bswap"?
 It would be less annoying to compile the original test_og.o 
 with gcc and then link it in.
If I understand correctly you mean compile the original file with gcc (`gcc test_og.c -o test_og.o`) and then link it with DMD (`dmd test.d test_og.o`)? Then what's the point of doing that? Isn't this how we did that all this time and why ImportC was created so we don't have to manually do the bindings? I'm confused...
Oct 16 2021
next sibling parent reply jfondren <julian.fondren gmail.com> writes:
On Saturday, 16 October 2021 at 08:19:41 UTC, rempas wrote:
 On Saturday, 16 October 2021 at 07:09:16 UTC, jfondren wrote:
 This test_og.c works (while obviously breaking some bswap 
 functions):
I don't know if I should have known that but what is "bswap"?
I came up with those `#define`s by looking at test_c.c as d complained about it. It includes these functions in the final result: ```c static __uint16_t __bswap_16 (__uint16_t __bsx) { return (__bsx); } static __uint32_t __bswap_32 (__uint32_t __bsx) { return (__bsx); } static __uint64_t __bswap_64 (__uint64_t __bsx) { return (__bsx); } ``` initially those were defined in terms of compiler intrinsics that d doesn't know about, and since they're not needed for your use, I fixed this in the direction of making them no-ops. They're part of stdlib.h, probably. What they do is endian swaps, like the stuff in std.bitmanip
 It would be less annoying to compile the original test_og.o 
 with gcc and then link it in.
If I understand correctly you mean compile the original file with gcc (`gcc test_og.c -o test_og.o`) and then link it with DMD (`dmd test.d test_og.o`)? Then what's the point of doing that? Isn't this how we did that all this time and why ImportC was created so we don't have to manually do the bindings? I'm confused...
importC is a new option, but it doesn't make old options go away, and in this specific case an older option would've been less trouble. That's all I'm saying.
Oct 16 2021
parent rempas <rempas tutanota.com> writes:
On Saturday, 16 October 2021 at 11:03:06 UTC, jfondren wrote:
 I came up with those `#define`s by looking at test_c.c as d 
 complained about it. It includes these functions in the final 
 result:

 ```c
 static __uint16_t
 __bswap_16 (__uint16_t __bsx)
 {
   return (__bsx);
 }
 static __uint32_t
 __bswap_32 (__uint32_t __bsx)
 {
   return (__bsx);
 }
  static __uint64_t
 __bswap_64 (__uint64_t __bsx)
 {
   return (__bsx);
 }
 ```

 initially those were defined in terms of compiler intrinsics 
 that d doesn't know about, and since they're not needed for 
 your use, I fixed this in the direction of making them no-ops.

 They're part of stdlib.h, probably. What they do is endian 
 swaps, like the stuff in std.bitmanip
Cool! It now makes sense now.
 importC is a new option, but it doesn't make old options go 
 away, and in this specific case an older option would've been 
 less trouble. That's all I'm saying.
Yeah agree, new options are a lot of times not there to make old options obsolete and not used. Tho in this case, I think ImportC will always makes sense against the old way of doing things. Even if you have to do a little bit of work, it will still be nothing compared if you had to make manual binding yourself... Thanks a lot for the help, have an amazing day!!
Oct 16 2021
prev sibling parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Saturday, 16 October 2021 at 08:19:41 UTC, rempas wrote:
 On Saturday, 16 October 2021 at 07:09:16 UTC, jfondren wrote:
 If I understand correctly you mean compile the original file 
 with gcc (`gcc test_og.c -o test_og.o`) and then link it with 
 DMD (`dmd test.d test_og.o`)? ...
While we're on this subject, I've been having similar issues now tried compiling rempas's example file with: ``` gcc test_og.c -c -o test_og.o dmd test.d test_og.o ``` and get the response: ``` test_og.c(1): Error: identifier or `(` expected test_og.c(6): Error: identifier or `(` expected ``` Platform is Ubuntu 20.04 gcc version 9.30 and dmd version v2.098.0. At first I tried compiling a script with fftw3 and thought it was something wrong with my script but when I tried it with your example, the same thing happened.
Oct 16 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Sunday, 17 October 2021 at 02:45:03 UTC, data pulverizer wrote:
 While we're on this subject, I've been having similar issues 
 now tried compiling  rempas's example file with:

 ```
 gcc test_og.c -c -o test_og.o
 dmd test.d test_og.o
 ```

 and get the response:

 ```
 test_og.c(1): Error: identifier or `(` expected
 test_og.c(6): Error: identifier or `(` expected
 ```
You're not doing this with the files in the thread, or you'd get ``` test.d(1): Error: module `test_c` is in file 'test_c.d' which cannot be read ``` as test.d is still importing test_c.c, a different file from test_og.o I get your error if the original test_og.c is used but test.d is modified to import test_og.c: ```d import test_og; void main() { hello_world(); } ``` In this case, your compilation to test_og.o doesn't matter; D is still trying to import test_og.c, and since that file has CPP `#include` directives which importC doesn't support, it's erroring out on those. To link in a C object rather than use importC, you'd need this test.d: ```d extern (C) void hello_world(); void main() { hello_world(); } ``` With which: ``` $ gcc test_og.c -c -o test_og.o $ dmd test.d test_og.o $ ./test Hello world!!! ```
Oct 16 2021
parent reply data pulverizer <data.pulverizer gmail.com> writes:
Okay I'm definitely trying to use `importC` rather than the 
regular `extern(C)` way. I can see where I went wrong. The steps 
for importC for header files are:

1. Prepend the following directives to `test_og.c` or whatever 
your interface c script is:

```
#define __restrict restrict
#define __asm__ asm
#define __extension__
#define __inline
#define __builtin_bswap16
#define __builtin_bswap32
#define __builtin_bswap64
```

2. Run the commands:

```
gcc -E -P test_og.c > test_c.c
dmd test.d test_c.c && ./test
```

which works. Now I've tried the same thing with library `fftw3` 
and getting:

```
Error: undefined identifier `__float128`
```

Which I guess I have to define somehow in the original c 
directives?
Oct 16 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Sunday, 17 October 2021 at 03:38:43 UTC, data pulverizer wrote:
 2. Run the commands:

 ```
 gcc -E -P test_og.c > test_c.c
 dmd test.d test_c.c && ./test
 ```

 which works. Now I've tried the same thing with library `fftw3` 
 and getting:

 ```
 Error: undefined identifier `__float128`
 ```

 Which I guess I have to define somehow in the original c 
 directives?
Yep, you have to look at test_c.c and fine the line with that error and decide what to do about it.
Oct 16 2021
next sibling parent reply data pulverizer <data.pulverizer gmail.com> writes:
I ended up defining `typedef struct __float128__ {unsigned long 
long x[2];} __float128__;` and doing a find and replace for 
`__float128` which is totally overkill since I won't be using it 
and according to the documentation, the D compiler doesn't 
support 128-bit floats yet though it has reserved keywords for it.

Many thanks.
Oct 16 2021
parent data pulverizer <data.pulverizer gmail.com> writes:
On Sunday, 17 October 2021 at 04:45:26 UTC, data pulverizer wrote:
 I ended up defining `typedef struct __float128__ {unsigned long 
 long x[2];} __float128__;` and doing a find and replace for 
 `__float128` which is totally overkill since I won't be using 
 it and according to the documentation, the D compiler doesn't 
 support 128-bit floats yet though it has reserved keywords for 
 it.

 Many thanks.
Decided the best idea to just to comment it out altogether.
Oct 16 2021
prev sibling next sibling parent reply data pulverizer <data.pulverizer gmail.com> writes:
Okay wow, this is amazing, I can now call R's standalone math 
library `Rmath.h` by converting:

```
//r2d_con.c
#define __restrict restrict
#define __asm__ asm
#define __extension__
#define __inline
#define __builtin_bswap16
#define __builtin_bswap32
#define __builtin_bswap64

#define MATHLIB_STANDALONE 1
typedef struct _Float128 {unsigned long long x[2];} _Float128;
#include "Rmath.h"
#include "R_ext/Random.h"
```

```
//callr
import r2d;
import std.random: unpredictableSeed;
import std.stdio: writeln;

void main()
{
   set_seed(unpredictableSeed(), unpredictableSeed());
   writeln("rgamma (2, 3): ", rgamma(2, 3));
}

```

Using:

```
gcc -E -P -I"/usr/share/R/include" -lRmath r2d_con.c > r2d.c
dmd callr.d -L-lRmath -L-lm && ./callr
```

Okay it's only the standalone library which is a small part of R, 
but this rocks. The PAHWAHR! Lol.
Oct 17 2021
next sibling parent data pulverizer <data.pulverizer gmail.com> writes:
On Sunday, 17 October 2021 at 10:46:30 UTC, data pulverizer wrote:
 Okay wow, this is amazing, I can now call R's standalone math 
 library `Rmath.h` by converting ...
Sorry you don't need `-lRmath` so the initial call should be: ``` gcc -E -P -I"/usr/share/R/include" r2d_con.c > r2d.c ```
Oct 17 2021
prev sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Sunday, 17 October 2021 at 10:46:30 UTC, data pulverizer wrote:
 Okay wow, this is amazing, I can now call R's standalone math 
 library `Rmath.h` by converting:

 [...]
Yeah it's pretty nice hey ☀️ But will become even more convenient later
Oct 17 2021
prev sibling parent reply data pulverizer <data.pulverizer gmail.com> writes:
Hi,

I'm getting an odd issue with ImportC when I import a header 
converted with `gcc -E -P ...` some of the types signatures in 
functions don't come through with their proper names but as 
`__tagXX` where `XX` is some number. It's got to the point where 
the type itself might get imported correctly, but the same type 
in a function might be `__tag28` or some other mangled name so 
when I create an instance of the proper type and try to call the 
respective function, I get a type error.

Also, with some definitions in the C file, when I try to `#undef` 
something to get some conditional C definitions to be converted 
with `gcc -E -P ...`, nothing happens.

Thanks.
Oct 21 2021
next sibling parent Imperatorn <johan_forsberg_86 hotmail.com> writes:
On Thursday, 21 October 2021 at 22:23:50 UTC, data pulverizer 
wrote:
 Hi,

 I'm getting an odd issue with ImportC when I import a header 
 converted with `gcc -E -P ...` some of the types signatures in 
 functions don't come through with their proper names but as 
 `__tagXX` where `XX` is some number. It's got to the point 
 where the type itself might get imported correctly, but the 
 same type in a function might be `__tag28` or some other 
 mangled name so when I create an instance of the proper type 
 and try to call the respective function, I get a type error.

 Also, with some definitions in the C file, when I try to 
 `#undef` something to get some conditional C definitions to be 
 converted with `gcc -E -P ...`, nothing happens.

 Thanks.
Just remember you're using stuff that's currently worked on
Oct 21 2021
prev sibling parent reply jfondren <julian.fondren gmail.com> writes:
On Thursday, 21 October 2021 at 22:23:50 UTC, data pulverizer 
wrote:
 Hi,

 I'm getting an odd issue with ImportC when I import a header 
 converted with `gcc -E -P ...` some of the types signatures in 
 functions don't come through with their proper names but as 
 `__tagXX` where `XX` is some number. It's got to the point 
 where the type itself might get imported correctly, but the 
 same type in a function might be `__tag28` or some other 
 mangled name so when I create an instance of the proper type 
 and try to call the respective function, I get a type error.
I'd first check that the type names look OK in the processed C. If they do, then it's an importc bug. Those are still getting reported, but yours might be new. Worth checking out. It might also be a bug that's been fixed since release--try dmd master on it. These were fixed a few days ago: fix Issue 22404 - importC: Error: cannot pass argument 'ENUMMEM' of type 'int' to parameter '__tag2 fix Issue 22402 - importC: Error: can't subtract '__tag2[1]' from pointer
 Also, with some definitions in the C file, when I try to 
 `#undef` something to get some conditional C definitions to be 
 converted with `gcc -E -P ...`, nothing happens.
d doesn't do any C preprocessing, so any problem here is with gcc. Your `#undef`s may be coming before the C preprocessor's own `#define`s and have no effect.
 Thanks.
Oct 21 2021
parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Thursday, 21 October 2021 at 23:06:18 UTC, jfondren wrote:
 On Thursday, 21 October 2021 at 22:23:50 UTC, data pulverizer 
 wrote:
 I'd first check that the type names look OK in the processed C. 
 If they do, then it's an importc bug. Those are still getting 
 reported, but yours might be new. Worth checking out.
I've double-checked and the types names are fine in translated C file.
 It might also be a bug that's been fixed since release--try dmd 
 master on it.
I have the latest compiler installed and I just double-checked by compiling dmd-master with the same result. The specific error is: ``` Error: function `Rf_allocVector(__tag28, long)` is not callable using argument types `(int, long)` cannot pass argument `REALSXP` of type `int` to parameter `__tag28` ``` Here `__tag28` should be `SEXPTYPE` which is an `enum int` containing `REALSXP`. Another (superficial by maybe related) issue is that `REALSXP` is an `SEXPTYPE` which is an `enum int` under the hood but dmd skips the `SEXPTYPE` description altogether, even though SEXPTYPE is correctly converted in the imported C file.
 Also, with some definitions in the C file, when I try to 
 `#undef` something to get some conditional C definitions to be 
 converted with `gcc -E -P ...`, nothing happens.
d doesn't do any C preprocessing, so any problem here is with gcc. Your `#undef`s may be coming before the C preprocessor's own `#define`s and have no effect.
I thought I'd ask anyway, it looks like a question for the R community, where `#undef R_NO_REMAP` in the script has no effect. This is unrelated to the first issue. As Imperatorn said (and I was aware as I asked the question) this is a new feature that is currently being worked on, and we should expect and report stuff like this. It's a great feature and lots of people will use it heavily. Including myself.
Oct 21 2021
parent reply Dave P. <dave287091 gmail.com> writes:
On Friday, 22 October 2021 at 06:11:35 UTC, data pulverizer wrote:
 On Thursday, 21 October 2021 at 23:06:18 UTC, jfondren wrote:
 [...]
I've double-checked and the types names are fine in translated C file. [...]
I think you ran into this [issue](https://issues.dlang.org/show_bug.cgi?id=22404). The bug fix isn’t part of a released dmd yet.
Oct 22 2021
parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Friday, 22 October 2021 at 16:16:22 UTC, Dave P. wrote:
 I think you ran into this 
 [issue](https://issues.dlang.org/show_bug.cgi?id=22404). The 
 bug fix isn’t part of a released dmd yet.
Yes that's the same error. When I try this: ``` ... this(R_xlen_t n) { SEXPTYPE _real_ = SEXPTYPE.REALSXP; _data = protect(allocVector(_real_, n)); unprotect(1); } ... ``` I get a slightly more interesting error message: ``` types.d(43): Error: cannot implicitly convert expression `14` of type `int` to `__tag28` ``` So it's not recognising `REALSXP` as an `SEXPTYPE`, it's as if it is treating `SEXPTYPE` like a `struct` rather than an `enum`. Also I was wandering, how long will it take release a fix for ImportC? I am aware that it is a new feature, the reason I ask is not to try to rush anyone but to plan my time better. Many thanks
Oct 23 2021
parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Saturday, 23 October 2021 at 16:39:08 UTC, data pulverizer 
wrote:
 ```
 ...
 this(R_xlen_t n)
   {
     SEXPTYPE _real_ = SEXPTYPE.REALSXP;
     _data = protect(allocVector(_real_, n));
     unprotect(1);
   }
 ...
 ```
Looking at that code, I realise didn't need the un/protect.
Oct 23 2021
parent reply data pulverizer <data.pulverizer gmail.com> writes:
On Saturday, 23 October 2021 at 17:42:32 UTC, data pulverizer 
wrote:
 On Saturday, 23 October 2021 at 16:39:08 UTC, data pulverizer 
 wrote:
 ```
 ...
 this(R_xlen_t n)
   {
     SEXPTYPE _real_ = SEXPTYPE.REALSXP;
     _data = protect(allocVector(_real_, n));
     unprotect(1);
   }
 ...
 ```
Looking at that code, I realise didn't need the un/protect.
Actually it's more complicated than that. On construction I do need to call `protect` and call `unprotect` or `unprotect_ptr` when the function in which the object is created returns. At the moment, I'm not even sure (or more likely do not think) that it is suitable to call it as part of the destructor. Anyway, that's an aside.
Oct 23 2021
parent data pulverizer <data.pulverizer gmail.com> writes:
On Sunday, 24 October 2021 at 05:54:43 UTC, data pulverizer wrote:

 Actually it's more complicated than that. On construction I do 
 need to call `protect` and call `unprotect` or `unprotect_ptr` 
 when the function in which the object is created returns. At 
 the moment, I'm not even sure (or more likely do not think) 
 that it is suitable to call it as part of the destructor. 
 Anyway, that's an aside.
Okay since it's stack allocated it's okay to call `unprotect` in the destructor if the object is a `struct` but not if it is a `class`.
Oct 23 2021