Calling inline C routine

Yes, I agree—good point.

From where can I grab the 1.29 distribution.

You want to do a git clone of the main development branch on GitHub. See Best Practices for Contributors — Chapel Documentation 1.28 for tips where, for your level of comfort with Chapel, you'll probably want to start with the second set of links ("Contributor Info" and "Getting Started with the Developer Certificate of Origin (DCO)").

-Brad

Why are not the C types size_t and ssize_t types given names beginning with c_. Just curious?

Silly me. That has been fixed in 1.29.

1 Like

In one place in the interoperability documentation, it says that pointer types may only point to local memory.

In another place, it says it should normally point to local memory.

Which is correct please?

You can make a pointer that points to anything you want (e.g. you could cast an integer to a pointer). However if you use (de-reference) such a pointer and it doesn't point to a valid memory location, bad things will happen (hopefully, core dump).

It does occasionally come up that we might want to create a c_ptr to some memory on another locale/node. In that case, we can create that pointer, but we have to keep track of what locale it came from, and be sure to only dereference / load / store with that pointer on its home locale.

Within the implementation of Chapel, there are other pointers (one case is that a ref variable or formal argument represents a kind of pointer). However these other pointers used in the implementation of Chapel are generally wide pointers, which means that they include their home locale along with the address, and that means you can dereference / load / store with them (and doing so just causes communication).

I'm certain that there is a better way to describe all of this in the document, so appreciate your help in that regard.

Thanks for the detail. I am sure I will have more questions. I will just push on.

A lot of this documentation started off as an individual README. Do we still call them a README or are they now a section by which as other parts of the documentation refer to them?

What makes more sense

as described in the section <a link>

or the far simpler

as described in <a link>

No strong preference here, though I think we should try to avoid forms that would only make sense if you're reading the docs online or in the original .rst files (because my understanding is that some people still do that, including potentially some typing this message).

I'm not sure how much the two forms reflect the non-web-based forms of the docs or just personal style/preference differences between people who first wrote, or last happened to touch, the document in question.

-Brad

I hope I am not being constricted by my oiwn inadequate knowledge.

Why is there a section on ref intents. Should not it be lumped in with the c_ptr(T) explanation?

Also, in that section, what do the words "they must be used differently in Chapel", mean. Obviously, if one is described as

extern proc byRef(ref x:c_int);

then it should be used as

byRef(x);

and if the other is

extern proc byPtr(x:c_ptr(c_int));

then it should be used as

byPtr(c_ptr(x));

Also, in Allowed Intents and Types, it says ... Since C passes and returns by value, a C argument such as int arg corresponds to an in intent argument in a Chapel extern proc . An argument such as int* ptrArg can be represented either with c_ptr(int) or with the ref intent in Chapel.

Isn't this much the same as said in ref intents. Shouldn't we just enhance that section if needed.

Also, I am not a fan of forward referencing things. I prefer to mention things early and back reference. Is that a no-no?

Are these words relevant any more ..... As of 1.23, there are several limitations on what types can be passed to or returned from extern or export functions and what intents can be used for the arguments to these functions.

In the Interoperability doco it says...

Note that, for numeric and pointer types, the default intent in Chapel is already const in

Is not the default intent for a pointer type const ref or am I reading something wrongly?

Hardly any of those numeric CTypes are used in the examples.

Should we rewrite the documentation using them so that we enforce some rigor on the doco?

For example, could I rewrite the section of Array Arguments as

Extern functions with array arguments are handled as a special case within the compiler. Given a C function with the prototype

void foo(long* x, size_t n);

This could be called in Chapel using

extern proc foo(x: [] c_long, n: c_size_t);

The Chapel compiler will then rewrite any calls to foo like this:

foo(x, 10); // -> foo(c_ptrTo(x), 10);

@damianmoz - thanks for looking at improving this document. I've consolidated my answers to your recent questions into this one post.

They mean just what you said was obvious in the above post. You seem to be understanding it correctly.

Yes but the purpose of this section is different. (Of course restructuring the document a bit could be OK).

I think this document has evolved quite a bit over time. It's current structure is probably not ideal. I think you'd have to rearrange some sections (or some of the content) to avoid back references. That would be reasonable if it's making the document more readable. (Of course that is subjective).

Yes I believe this is the current situation (so it could just as well say "In 1.23 and later" or just leave out the version information entirely).

Default intent for a c_ptr or c_void_ptr would be const in. Default intent for a class instance is const in pointer to the instance, which you could view as a const ref pointer to the fields (but I don't). So, probably you are reading something wrong. (Or there is something wrong/confusing in the docs, somewhere).

Generally speaking, more examples is good. However, I don't think the document needs examples for every type just for the sake of examples. Is there something you think they would communicate that is missing?

Your adjustment here to lead with the C prototype (which would normally already exist, for an extern proc situation) makes sense to me and looks like a good improvement.

Thanks. That gives me some direction.

I am still not clear what the rules/preferrence is between using a ref in an argument list or a c_ptr(T).

It seems that the latter is generated automatically from some extern block declarations.,

In the spirit of c_void_ptr, and out of curiosity, should not the names of the pointer types be

c_data_ptr(T)
c_proc_ptr

instead of c_ptr(T) an c_fn_ptr. Just a thought. When will c_string be deprecated in favour of

c_data_ptr(int(8))

If it is upcoming in 1.30 or whatever, I might as well make the change to what I am doing now.

I am still not clear what the rules/preferrence is between using a ref in an argument list or a c_ptr(T).

The only time you should be using c_ptr(T) is for interoperability with C / other languages, or perhaps in some rare corner cases. For example, when you receive a pointer from an extern function, are about to pass a pointer to it, or are somewhere in between.

A ref argument is what I expect to see in purely-Chapel code.

Or perhaps you are asking when to use ref vs. c_ptr() in an argument list of an extern or export function? I do not have a good sense of this other than the above, so I would lean towards c_ptr().

Note that a ref argument can correspond to a "wide" pointer in the generated code, which is a C pointer plus locale information. A c_ptr() does not carry the locale information; dealing with cross-locale references is your responsibility when using c_ptrs.

P.S. This would make a good StackOverflow question.

Thanks Vass. You have made it more clear.

I am trying to rewrite the Interoperability Technotes. There are references in the existing Technotes thatt talk about using ref arguments in an extern or export function. I might remove those example from the main body of the text to avoid confusion and use c_ptr(T) across the board.

Sorry. I do not look ar the Chapel Stack Overflow stuff. I have enough trouble keeping up to date with the latest in Discourse and Github. And all my other mailing lists like groff, musl, IEEE 754, and so on. And then there is my day which is all about CAE.

Hello Damian, I am glad this helped. You are welcome to stay out of StackOverflow.

I am checking with the team about ref arguments, to make sure that our direction is correct.

With your reply making things clearer, I reread the Technotes. For a C prototype

void foo(double *x);

You can define the Chapel side of the interface as

extern void foo(x : c_ptr(real));

in which case you need to use foo as

var x : real(64) = 7.5;

foo(c_ptrTo(x));

i.e. you need to explicitly construct the pointer!

Or, and this is the preferred method, you can define the Chapel side of the interface as

extern proc foo(ref x : real(64));

and then use it as

var x : real(64) = 7.5;

foo(x);

I have no idea what the autogenerated interface is in the scenario where you use an extern block. That piece of information is missing from the Technotes (and elsewhere).

Interestingly, when you want to pass a function pointer, you need to explicitly construct that function point as seen in the Technotes

extern proc foo(f: c_fn_ptr);

foo(c_ptrTo(bar));

proc bar(x: c_int): c_double {
  ...
}

While the use of a ref is cleaner for data, forcing programmers to construct the pointer in ALL cases, data or functions, seems like a more consistent approach. So, I am still none the wiser. Mind you, I wasn't all that wise before I started using Chapel 10 years ago, but that is another problem.