加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 使用来自C的内存地址的Julia读/写结构数据

发布时间:2020-12-16 07:21:26 所属栏目:百科 来源:网络整理
导读:我将我的应用程序嵌入到Julia中,我需要一种从Julia和C读取/写入相同结构的好方法. 在Python中我可以简单地做到: ffi.cdef(""" struct keyboard_s { int forward; int backward; int left; int right; int jump; } struct keyboard_s *app_get_keyboard();""
我将我的应用程序嵌入到Julia中,我需要一种从Julia和C读取/写入相同结构的好方法.

在Python中我可以简单地做到:

ffi.cdef("""
    struct keyboard_s {
        int forward;
        int backward;
        int left;
        int right;
        int jump;
    }

    struct keyboard_s *app_get_keyboard();
"""

app = ffi.dlopen("app.dll")

thekeyboard = app.app_get_keyboard();

thekeyboard.forward = 1; # this would immediatly change the memory in C

但是,我在Julia和Julia中尝试这样的事情总是只是复制数据并且无法从C更改外部存储器地址:

type keyboard_s
    forward::Int32
    backward::Int32
    left::Int32
    right::Int32
    jump::Int32
end

# lets imply this would return the memory struct just like app_get_keyboard()
# I just use malloc(sizeof(keyboard_s)) so everybody here can test for themselves...
address = ccall(:malloc,(Int64),(Int64,),sizeof(keyboard_s))

# address is now a valid Int64 address,so lets map it as pointer of type keyboard_s
ptr = Ptr{keyboard_s}(address)

# thekeyboard contains now the random data from the c static memory
thekeyboard = unsafe_load(ptr)

# this will change only the value of "thekeyboard",# it doesn't touch C the Int64 address memory pointer...
thekeyboard.forward = 123 # this has no effect on the real memory address :(

# lets load the keyboard again from same address
thekeyboard = unsafe_load(ptr)

thekeyboard.forward == 123 # this is false! no effect whatsoever in C memory from Julia

我怎么能在Julia中与C共享结构的内存地址?

解决方法

好吧,我想出了一个很好的出路,这并不觉得太尴尬.我基本上重载[]运算符来通过符号访问struct字段,如下所示:

thekeyboard[:forward] = 123

代码:

function offsetof(type_,member::Symbol)
  for (i,item) in enumerate(fieldnames(type_))
    if item == member
      return fieldoffset(type_,i)
    end
    #print(typeof(i))
  end
  # what to do when symbol not in type_?
  throw("$type_ has no member named $member")
end

function GetStructType(type_,item) in enumerate(fieldnames(type_))
    if item == member
      return fieldtype(type_,i)
    end
    #print(typeof(i))
  end
  # what to do when symbol not in type_?
  throw("$type_ has no member named $member")
end

function Base.getindex(ptr::Ptr{T},s::Symbol) where {T}
  address = UInt(ptr)
  if address == 0
    throw("Base.getindex(Ptr::{$T}) would dereference a NULL pointer")
  end
  offset = offsetof(T,s)
  fieldtype = GetStructType(T,s)
  fieldptr = Ptr{fieldtype}(address + offset)
  #log("Symbol $s $ptrtype address=$address offset=$offset fieldtype=$fieldtype ptr=$ptr fieldptr=$fieldptrn")
  #return 123
  return unsafe_load(fieldptr)
end

function Base.setindex!(ptr::Ptr{T},value,s::Symbol) where {T}
  address = UInt(ptr)
  if address == 0
    throw("Base.setindex!(Ptr) would write to a NULL pointer")
  end
  offset = offsetof(T,s)
  fieldptr = Ptr{fieldtype}(address + offset)
  #log("Symbol $s $ptrtype address=$address offset=$offset fieldtype=$fieldtype ptr=$ptr fieldptr=$fieldptrn")
  unsafe_store!(fieldptr,value)
  return value
end

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读