我想将字符串从 Fortran 传递到 C/C++。这是我的 Fortran 代码:
subroutine zdplaskinGetSpeciesName(cstring, index) bind(C, name='zdplaskinGetSpeciesName')
use iso_c_binding
use ZDPlasKin
implicit none
integer, intent(in) :: index
CHARACTER(10), TARGET :: fstring = ''
TYPE(C_PTR) :: cstring
fstring = species_name(index+1)
cstring = c_loc(fstring)
end subroutine zdplaskinGetSpeciesName
ZDPlasKin 是一个具有species_name(i) 的模块。
extern "C" void zdplaskinGetSpeciesName(char* cstring[], size_t* index);
char* cstring[1];
size_t index = 1;
zdplaskinGetSpeciesName(cstring, &index);
string speciesName = string(cstring[0]);
cout << speciesName << endl;
此方法的输出似乎没问题。但是,我想修剪尾随空格(character(10) 提供额外的空间),以便我的 C++ 代码可以正确读取字符串。我尝试了另一种方式。
subroutine zdplaskinGetSpeciesName(cstring, index) bind(C, name='zdplaskinGetSpeciesName')
use iso_c_binding
use ZDPlasKin
implicit none
integer, intent(in) :: index
CHARACTER(:), allocatable, TARGET :: fstring
TYPE(C_PTR) :: cstring
fstring = trim(species_name(index+1))
cstring = c_loc(fstring)
end subroutine zdplaskinGetSpeciesName
但是这样我得到了一些奇怪的符号。
我想把事情做对,这样我以后就不用担心了。内存泄漏不是我想要的。所以我想我会尝试你建议的替代方法。我想我想知道的是我怎么知道我是否需要释放一个指针。这是我在 StackOverflow 上找到的另一个代码(尽管这个代码将 C++ 字符串传递给 Fortran。https://stackoverflow.com/a/30430656/721644)
你觉得这个可以用吗?或者可能存在内存泄漏。你也可以给我一些关于你建议的替代方式的提示吗?
最佳答案
许多其他问题都处理了这个的变体。为关闭搜索完全相同的拷贝可能没有希望,但我强烈建议您搜索并阅读这些问题和答案。
C 字符串以 null 结尾。如果要修剪它,只需将空字符放在正确的位置即可。实际上,您在第一个版本中根本不是空终止字符串,因此很容易出现缓冲区溢出。
但更糟糕的是,变量 fstring 只是函数的局部变量。永远不要将指针传递给局部变量。
所以,第一个版本真的应该是
subroutine zdplaskinGetSpeciesName(cstring, index) bind(C, name='zdplaskinGetSpeciesName')
use iso_c_binding
use ZDPlasKin
implicit none
integer, intent(in) :: index
CHARACTER(11), POINTER :: fstring
TYPE(C_PTR) :: cstring
allocate(fstring)
fstring = species_name(index+1)
fstring(11:11) = c_null_char
cstring = c_loc(fstring)
end subroutine zdplaskinGetSpeciesName
要修剪字符串,只需将空字符放在正确的位置
integer :: len
...
len = len_trim(fstring)
fstring(len+1:len+1) = c_null_char
您还可以使用指向长度字符数组的指针,该数组的长度将匹配字符串的长度 + 1 或类似于第二种方法的延迟长度 (character(:)) 字符指针。请记住始终为空终止保留 1 个字符。
现在代码会有内存泄漏。要避免内存泄漏,必须从 Fortran 中释放字符串!因此,您必须创建一个特殊的子程序来释放这些指针。
另一种方法是从 C++ 传递一个指向缓冲区的指针,然后只用 Fortran 语言填充字符串。我实际上更喜欢那样。您可以在 C++ 中使它以 null 终止,只是确保不要让 Fortran 覆盖终止字符。
你可以试试:
subroutine zdplaskinGetSpeciesName(cstring, index) bind(C, name='zdplaskinGetSpeciesName')
use iso_c_binding
use ZDPlasKin
implicit none
integer, intent(in) :: index
TYPE(C_PTR), intent(in) :: cstring
CHARACTER(kind=C_CHAR), POINTER :: fstring(:)
integer :: i, c_len, name_len
c_len = c_strlen(cstring)
c_f_pointer(cstring, fstring, [c_len])
associate(name => species_name(index+1))
name_len = trim_len(name)
do i = 1, name_len
fstring(i) = name(i:i)
end do
fstring(name_len+1:name_len+1)
end do
end subroutine zdplaskinGetSpeciesName
未经测试。您有责任从 C++ 提供足够大的空终止缓冲区。 c_strlen 可以在 http://fortranwiki.org/fortran/show/c_interface_module 找到
要 100% 符合标准,您应该使用长度为 1 的字符数组 character(kind=c_char),但字符串很可能在实践中起作用。
关于c++ - 将字符串从 Fortran 传递到 C/C++ 的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45330436/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco