GVKun编程网logo

如何从Golang访问C指针数组(golang interface 指针)

24

本篇文章给大家谈谈如何从Golang访问C指针数组,以及golanginterface指针的知识点,同时本文还将给你拓展10、C语言——指针与一维数组(指针数组与数组指针)、73,QT指针数组实战(指

本篇文章给大家谈谈如何从Golang访问C指针数组,以及golang interface 指针的知识点,同时本文还将给你拓展10、C语言 —— 指针与一维数组(指针数组与数组指针)、73,QT指针数组实战(指针数组与数组指针)、C++——指针2-指向数组的指针和指针数组、C/CPP 指针变量 | 数组指针 | 指针数组 | 野指针 | 空指针等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

如何从Golang访问C指针数组(golang interface 指针)

如何从Golang访问C指针数组(golang interface 指针)

我正在使用FFmpeg为Windows平台编写一个应用程序,它是golang包装器goav,但是我在理解如何使用C指针获取对数组的访问方面遇到了麻烦。

我试图获取存储在AVFormatContext类中的流以供使用,并最终将帧添加到OpenGl中的纹理以使视频播放器具有出色的过渡效果。

我认为了解如何转换和访问C数据将使编码变得容易得多。

我已经删除了C代码的所有相关部分,包装程序和我的代码,如下所示:

C代码-libavformat / avformat.h

typedef struct AVFormatContext {     unsigned int nb_streams;     AVStream **streams; }

Golang Goav包装器

package avutil//#cgo pkg-config: libavformat//#include <libavformat/avformat.h>import "C"import (    "unsafe")type Context C.struct_AVFormatContext;func (ctxt *Context) StreamsGet(i uintptr) *Stream {    streams := (**Stream)(unsafe.Pointer(ctxt.streams));    // I think this is where it''s going wrong, I''m brand new to this stuff     return (*Stream)(unsafe.Pointer(uintptr(unsafe.Pointer(streams)) + i*unsafe.Sizeof(*streams)));}

我的Golang代码

package mainimport "github.com/giorgisio/goav/avformat"func main() {    ctx := &avformat.Context{} // the actual function to initiate this does an mallocz for the streams    stream := ctx.StreamsGet(0)    //do stuff with stream...}

在C语言中,我似乎只需要执行stream[i],但这行不通,因此我在这里使用了我的问题中的技术为包装器添加了一个函数。但是我没有得到数据。看来我正在获取指向内存中随机位置的指针。那么,如何从golang中访问这些元素?任何资源也将有所帮助;我将为此花很多时间。

答案1

小编典典

正如您所注意到的,问题出在以下代码中:

func (ctxt *Context) StreamsGet(i uintptr) *Stream {    streams := (**Stream)(unsafe.Pointer(ctxt.streams));    // I think this is where it''s going wrong, I''m brand new to this stuff     return (*Stream)(unsafe.Pointer(uintptr(unsafe.Pointer(streams)) + i*unsafe.Sizeof(*streams)));}

在代码中,变量streams双指针,因此将offset添加到的结果streams也是双指针(即类型为**Stream)。但是,在您的摘录中,它被强制转换*Stream为不正确的。正确的代码是:

func (ctxt *Context) StreamsGet(i uintptr) *Stream {    streams := (**Stream)(unsafe.Pointer(ctxt.streams))    // Add offset i then cast it to **Stream    ptrPtr := (**Stream)(unsafe.Pointer(uintptr(unsafe.Pointer(streams)) + i*unsafe.Sizeof(*streams)))    return *ptrPtr}

补充说明:
如果要避免在Goside 进行指针运算,则可以定义一个_辅助_函数,用于访问C端的指针元素(即流),如下所示:

/*void * ptr_at(void **ptr, int idx) {    return ptr[idx];}struct AVStream * stream_at(struct AVFormatContext *c, int idx) {    if (i >= 0 && i < c->nb_streams)        return c->streams[idx];    return NULL;}*/import "C"import (    "unsafe")type Context C.struct_AVFormatContexttype Stream C.struct_AVStreamfunc (ctx *Context) StreamAt(i int) *Stream {    p := (*unsafe.Pointer)(unsafe.Pointer(ctx.streams))    ret := C.ptr_at(p, C.int(i))    return (*Stream)(ret)}func (ctx *Context) StreamAt2(i int) *Stream {    ret := C.stream_at((*C.struct_AVFormatContext)(ctx), C.int(i))    return (*Stream)(ret)}

您可以选择ptr_at接受通用(任何)双指针作为其参数的函数,也可以选择stream_at仅接受指向其的指针作为其参数的更具体的函数AVFormatContext。:前者的方法可以从任何双指针如用于接入元件AVProgram**AVChapter **等等。后一种方法是优选的,如果我们需要实现额外的处理,如边界检查。

10、C语言 —— 指针与一维数组(指针数组与数组指针)

10、C语言 —— 指针与一维数组(指针数组与数组指针)

1、使用指针修改数组元素

int array[2];
int *p;
p = array;
// 或 p = &a[0];

*p = 10;

printf("a[0]=%d\n", a[0]);    // 输出:a[0]=10


2、使用指针遍历数组

// a、平常我们是这样遍历数组的
int array[3] = {1, 2, 3};
for(int i=0; i<3; i++) {
    printf("a[%d]=%d\n", i, a[i]);
}

// b、用指针可以这样遍历数组
// 如果 p 是指向数组array的首元素array[0]
// 那么 p+1 则会根据数据类型 int 从而指向数组array的第二个元素array[1]
// 在16位编译器环境下,p+1代表增加2个字节
int *p = array;
for(int i=0; i<3; i++) {
    printf("a[%d]=%d\n", i, *(p+i));
}

// c、指针遍历2
// 此种方法相比于上一种方法不同的是:上一种方法指针p不变,而这种p每循环一次就改变一个
for(int i=0; i<3; i++) {
    printf("a[%d]=%d\n", i, *(p++));
}

// d、指针遍历3
// 数组跟指针有着密不可分的关系,array[i]也可以写成*(array+i)
for(int i=0; i<3; i++) {
    printf("a[%d]=%d\n", i, *(array+i));
}


3、指针,数组与函数参数

// 定义一个修改数组首元素的函数
void change(char c[]) {
    c[0] = 0;
}

void main() {
    char a[3];
    change(a);    // 传入数组地址
    printf("a[0]=%d\n", a[0]);    // 输入:a[0]=10
}

// 也可传入指针
void main() {
    char a[3];
    char *p = a;
    change(p);    // 传入地址
    printf("a[0]=%d\n", a[0]);    // 输入:a[0]=10
}

// 当然,change函数还可以改成这样
void change(char *c) {
    *c = 10;
    // 或c[0] = 10;
}

    


4、指针数组与数组指针

    a、指针数组:int *p[n];

    • 因为优先级:() > [] > *

    • p首先是一个数组,再由 int * 说明这是一个整型指针数组

    • 即数组里的元素都存放着变量的地址

    b、数组指针(行指针):int (*p)[n];

    • p是一个指针,指向一个整型的一维数组

int a[3][4];
int (*p)[4];    //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

// 所以数组指针也称指向一维数组的指针,亦称行指针。




73,QT指针数组实战(指针数组与数组指针)

73,QT指针数组实战(指针数组与数组指针)

 1  //指针数组,每一个指针都是一个MainWindow
 2 //    MainWindow *w[3][4];
 3 //    for(int i=0;i<3;i++)
 4 //    {
 5 //        for(int j=0;j<4;j++)
 6 //        {
 7 //            w[i][j] = new MainWindow;
 8 //            w[i][j]->move(i*100,j*100);
 9 //            w[i][j]->resize(100,100);
10 //            w[i][j]->show();
11 //        }
12 //    }
13 
14     //一个指针指向一个数组指针,这个数组有五列
15     MainWindow *(*w)[5] = new MainWindow* [4][5];
16 
17     for(int i=0;i<3;i++)
18     {
19         for(int j=0;j<4;j++)
20         {
21             w[i][j] = new MainWindow;
22             w[i][j]->move(i*100,j*100);
23             w[i][j]->resize(100,100);
24             w[i][j]->show();
25         }
26     }

 

C++——指针2-指向数组的指针和指针数组

C++——指针2-指向数组的指针和指针数组

7.4 指向数组元素的指针

声明与赋值

例:int a[10], *pa;

    pa=&a[0]; 或 pa=a[p1] ;

通过指针引用数组元素,经过上述声明及赋值后:

*pa就是a[0],*(pa+1)就是a[1],... ,*(pa+i)就是a[i].

a[i], *(pa+i), *(a+i), pa[i]都是等效的。不能写 a++,不能给数组名赋值或者试图改变其值,因为a是数组首地址是常量。

例子:使用三种方法输出数组元素

使用数组名和下标

使用数组名指针运算

使用指针变量

int main()

{   int a[10];   int i;

   for(i=0; i<10; i++)

     cin>>a[i];

   cout<<endl;

   for(i=0; i<10; i++)

     cout<<a[i];}

int main()

{   int a[10];   int i;

   for(i=0; i<10; i++)

      cin>>a[i];

   cout<<endl;

   for(i=0; i<10; i++)

     cout<<*(a+i);}

int main()

{   int a[10];   int *p, i

   for(i=0; i<10; i++)

        cin>>a[i];

   cout<<endl;

   for(p=a; p<(a+10); p++)

        cout<<*p;}

7.5 指针数组

指针数组的元素是指针型,例如:point *pa[2];由pa[0] ,pa[1]两个指针组成。

#include <iostream>

using namespace std;

int main()

{

         int line1[]={1,0,0};      //声明数组,矩阵的第一行

         int line2[]={0,1,0};      //声明数组,矩阵的第二行

         int line3[]={0,0,1};      //声明数组,矩阵的第三行

        

         int *p_line[3];     //声明整型指针数组

         p_line[0]=line1; //初始化指针数组元素

         p_line[1]=line2;

         p_line[2]=line3;

        

         cout<<"Matrix test:"<<endl;         //输出单位矩阵

         for(int i=0;i<3;i++)     //对指针数组元素循环

         {

             for(int j=0;j<3;j++)      //对矩阵每一行循环

             {   cout<<p_line[i][j]<<" ";   }

             cout<<endl;

         }

}

  

#include <iostream>

using namespace std;

int main()

{

         int array2[2][3]={{11,12,13},{21,22,23}};     //声明二维int型数组

         for(int i=0;i<2;i++)

      {

             cout<<*(array2+i)<<endl;   //输出二维数组第i行的首地址

             for(int j=0;j<3;j++)

          {  cout<<*(*(array2+i)+j)<<" ";    }       //逐个输出二维数组第i行元素值

//写成 {  cout<<*array2[i][j]<<" ";  }比较好。

             cout<<endl;

         }

  

}//输出结果为:

0X0065FDE0

11,12,13

0X0065FDEC

21,22,23

C/CPP 指针变量 | 数组指针 | 指针数组 | 野指针 | 空指针

C/CPP 指针变量 | 数组指针 | 指针数组 | 野指针 | 空指针

普通变量和指针变量

共性

PS:

可见这4个函数的汇编指令完全一致,无论是什么类型的指针变量,对指针变量的读写跟普通变量没有任何区别,所谓的指向只是描述指针变量的值时多少而已,就读写而言,指针变量跟普通变量没有任何区别。

特性

普通变量的值常常用于数学计算,而指针变量常常用来定位内存。

普通变量可以不赋初值,但是指针变量的初值必须万分慎重,因为未来的*操纵会以这个初值为目标内存地址,往里面读写数据(可以才C primer plus中看到相应分析)

所以给指针变量赋值一定要是合法合理的内存地址,读取非法的地址程序会修改其他的内存中的值导致程序崩溃,野指针。

空指针和野指针

野指针:定义了一个指针变量,如果没有进行初始化,系统就会有可能随机赋值一个地址给这个指针变量,也就是说,这个指向指向一个未知的区域。

空指针:空指针不是指向常数0,只指向地址0,即NULL,其实换句话说,指针的本质就是地址嘛,空指针就是指针本身的值(地址)为0空指针的作用是防止野指针的出现,因为我们不能知道野指针到底指向哪里,所以我们也无法判断一个指针是否是野指针,这样很危险,但如果养成将指针初始化为空指针的习惯,我们就能判断出这个指针是不是有效的(判断是不是NULL就可以了)通用指针一般都用在函数传参,实现所谓的“多态”,但到函数里面使用时,一般还是被转换成具体类型的指针。

指针变量的+-运算

指针变量的加减运算:也就是做地址偏移,不同 的指针类型偏移的步长不同。

PS:

区分指针数组int *a[3]和数组指针int (*a)[3],前者时存放指针的数组,后者是指向数组的指针。

指针数组和数组指针

int *b可以用来定义数组

int a = [1,2,3,4,5];
int *b = a;

int (*b)[5]用来指向数组

int a = [1,2,3,4,5];
int (*b)[5] = a;

int *b[5]用来存放指针

int *b[5] =[&a,&b,&c,&d,&e] ;

数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。

如要将二维数组赋给一指针,应这样赋值:

int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a;    //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
p++;    //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

指针数组 定义 int *p[n]; []优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]…p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 p=a; 这里p表示指针数组第一个元素的值,a的首地址的值。 如要将二维数组赋给一指针数组:

int *p[3];
int a[3][4];
p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
for(i=0;i<3;i++)
	p[i]=a[i]

这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2] 所以要分别赋值。

这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。 还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。 比如要表示数组中i行j列一个元素: *(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

优先级:()>[]>*

数组指针分析:在这里“()”的优先级比“[]”高,“*”号和p2 构成一个指针的定义,指针变量名为p2,int 修饰的是数组的内容,即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚p2 是一个指针,它指向一个包含10 个int 类型数据的数组,即数组指针。

关于如何从Golang访问C指针数组golang interface 指针的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于10、C语言 —— 指针与一维数组(指针数组与数组指针)、73,QT指针数组实战(指针数组与数组指针)、C++——指针2-指向数组的指针和指针数组、C/CPP 指针变量 | 数组指针 | 指针数组 | 野指针 | 空指针的相关信息,请在本站寻找。

本文标签: