抛弃指向 const 的指针数组中的常量性,以及有关 C 的其他问题
我正在运行一些代码来测试 MATLAB mex 函数中的多线程(我知道 MATLAB 不是线程安全的......我只是想看看会发生什么)。 MATLAB C 代码函数的入口点具有帖子底部代码片段中的 mexFunction 函数的签名。 由于我本质上想将该函数的参数传递到使用 pthread 创建的另一个线程中,因此我需要将所有内容捆绑到一个结构中。 mexFunction 的签名(我无法更改)包含指向 mxArray 的指针数组,但是我无法直接在结构定义中包含指向 mxArray 的指针数组,因为从那时起我无法分配给结构的该字段(无法分配给数组)。 例如,这不起作用:
typedef struct MexFunArgs {
int nrhs;
const mxArray *prhs[];
} MexFunArgs;
/* ... now within the mexFunction ... */
MexFunArgs mfa;
mfa.prhs = prhs;
解决此问题的第一个想法是将结构定义更改为:
typedef struct MexFunArgs {
int nrhs;
const mxArray **prhs;
} MexFunArgs;
但是,当我在另一个线程中使用此结构时,我需要按顺序强制转换回指针数组将其传递给 mexCallMATLAB 函数,据我所知这是无法完成的(如果我错了,请纠正我!)。
因此,我想改为将结构定义更改为:
typedef struct MexFunArgs {
int nrhs;
const mxArray *(*prhs)[];
} MexFunArgs;
即,指向 mxArray 指针数组的指针。 这解决了赋值问题(尽管编译器仍然抱怨指针类型不兼容,原因我不明白)。 然而,事实证明 mexCallMATLAB 函数并不采用指向 const mxArray 的指针数组,而是采用指向非 const mxArray 的指针数组。 所以现在我想知道是否有一种方法可以将指针的 const 方面丢弃到指向 const mxArrays 的指针数组。 我不知道该怎么做......以下是不合法的:
(mxArray *(*)[])
可以做到吗? 如果不是,我正在尝试做的事情(将这些参数完好无损地传递给另一个线程,以便它们可以在没有编译器抱怨的情况下使用)可以在C中以其他方式实现吗?
以下是我目前使用的完整代码,它按预期运行,但在编译时会产生警告。 我讨厌警告,并希望它消失。 实现这一目标的正确方法是什么?
#include <pthread.h>
#include <unistd.h>
#include <mex.h>
typedef struct MexFunArgs {
int nrhs;
mxArray *(*prhs)[];
} MexFunArgs;
void *do_thread(void *args) {
MexFunArgs *mfa = (MexFunArgs*) args;
mexCallMATLAB(0, NULL, mfa->nrhs, *mfa->prhs, "disp");
pthread_exit(NULL);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int num;
if (nrhs < 1)
mexErrMsgTxt("not enough input arguments");
else
num = mxGetScalar(prhs[0]);
MexFunArgs mfa;
mfa.nrhs = nrhs;
mfa.prhs = &prhs[1]; /* <-- threads.c:29: warning: assignment from incompatible pointer type */
pthread_t threads[num];
int rc, t;
for (t = 0; t < num; t++) {
mexPrintf("In main: creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, do_thread, (void *) &mfa);
if (rc)
mexErrMsgTxt("Problem with return code from pthread_create()");
}
return;
}
I have a bit of code I'm running to test multithreading in MATLAB mex functions (I know MATLAB isn't thread safe... I'm just playing around to see what happens). The entry point to MATLAB C code functions has the signature of the mexFunction function in the code snipped at the bottom of the post. Since I want to essentially pass the arguments from this function into another thread created using pthreads, I need to bundle everything up into a structure. The signature of the mexFunction (which I cannot change) includes an array of pointers to mxArray, however I can't directly include an array of pointers to mxArray in the structure definition since then I couldn't assign to that field of the structure (can't assign to an array). For example, this doesn't work:
typedef struct MexFunArgs {
int nrhs;
const mxArray *prhs[];
} MexFunArgs;
/* ... now within the mexFunction ... */
MexFunArgs mfa;
mfa.prhs = prhs;
A first thought to fix this is to change the structure definition to this:
typedef struct MexFunArgs {
int nrhs;
const mxArray **prhs;
} MexFunArgs;
However, then when I use this structure in the other thread, I would need to cast back to an array of pointers in order to pass it to the mexCallMATLAB function, which as far as I know can't be done (please correct me if I'm wrong here!).
So, I thought instead I would change the structure definition to this:
typedef struct MexFunArgs {
int nrhs;
const mxArray *(*prhs)[];
} MexFunArgs;
I.e., a pointer to an array of pointers to mxArray. This solves the assignment issue (though the compiler still complains about incompatible pointer types for reasons I don't understand). However, it turns out the mexCallMATLAB function doesn't take an array of pointers to const mxArrays, but instead an array of pointers to non-const mxArrays. So now I'd like to know if there's a way of casting away the const aspect of my pointer to an array of pointers to const mxArrays. I have no idea how to do that... the following isn't legal:
(mxArray *(*)[])
Can it be done? If not, is what I'm trying to do (pass these arguments to the other thread unscathed in such a way that they can be used without the compiler whining) possible in some other way in C?
The following is the complete code I'm using at the moment, which runs as expected, but produces a warning when compiled. I hate warnings, and want it to go away. What is the right way of making that happen?
#include <pthread.h>
#include <unistd.h>
#include <mex.h>
typedef struct MexFunArgs {
int nrhs;
mxArray *(*prhs)[];
} MexFunArgs;
void *do_thread(void *args) {
MexFunArgs *mfa = (MexFunArgs*) args;
mexCallMATLAB(0, NULL, mfa->nrhs, *mfa->prhs, "disp");
pthread_exit(NULL);
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int num;
if (nrhs < 1)
mexErrMsgTxt("not enough input arguments");
else
num = mxGetScalar(prhs[0]);
MexFunArgs mfa;
mfa.nrhs = nrhs;
mfa.prhs = &prhs[1]; /* <-- threads.c:29: warning: assignment from incompatible pointer type */
pthread_t threads[num];
int rc, t;
for (t = 0; t < num; t++) {
mexPrintf("In main: creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, do_thread, (void *) &mfa);
if (rc)
mexErrMsgTxt("Problem with return code from pthread_create()");
}
return;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
该警告是由于分配
指向
请记住,您只能安全地分配给更合格的类型。
这些是不同的类型。 您要么禁用该特定行的警告,要么使用强制转换——两者同样危险。
另请注意,如果您使用基于 C99 的编译器进行编译,则 mxArray 声明中结构的空
[]
声明一个可变长度数组。 这是你想要的吗?The warning is due to assignment of
to
Remember, you can only safely assign to a more qualifed type.
These are different types. You either disable the warning for that particular line or use a cast -- both equally dangerous.
Also note, if you are compiling with a C99-based compiler, the structure's empty
[]
in the mxArray declaration, declares a variable-length-array. Is this what you want?找到了一个让一切顺利进行的方法。 因为数组和指针在函数签名中的处理方式相同,所以我只是将 mexFunction 更改为采用 mxArray ** 而不是 mxArray *thing[]。 那么转换就没有问题,因为不需要转换为数组类型(非法)。
Figured out a way to get everything working happily. Because arrays and pointers are treated identically in function signatures, I just changed the mexFunction to take mxArray ** instead of mxArray *thing[]. Then there's no problem casting, since there's no need to cast to an array type (illegal).
根据您的标题进行大胆猜测,我认为您还没有掌握指针的常量与它所指向的对象的常量之间的区别。
请参阅 为什么这允许从 ( char *) 到 (const char *)? 的示例可以指导您。
对于和其他问题部分,为什么不将它们分成单独的问题。 这可能有助于获得您寻求的答案。
Taking a wild guess based on your headline I assume that you have not yet grasped the difference between the constness of a pointer vs. the constness of the object it points too.
See Why does this allow promotion from (char *) to (const char *)? for an example that can guide you.
For the and other questions part, why don't you split them into seperate questions. That may help getting the answers you seek.