b***@vivaldi.net
2016-12-30 03:34:11 UTC
I've been experimenting with ways to call C and COBOL functions without need for a wrapper.
Tests are working out well with (a very platform specific) inline assembly layer.
The test COBOL
identification division.
program-id. sample.
data division.
linkage section.
01 one usage binary-long.
01 two usage binary-long.
procedure division using by value one two.
sample-main.
display "GnuCOBOL got " one ", " two
compute return-code = one + two
goback.
end program sample.
And the test Unicon
#
# testcob.icn, test calling COBOL without wrapper
#
$include "natives.inc"
procedure main()
# will be RTLD_LAZY | RTLD_GLOBAL (so add to the search path)
addLibrary := loadfunc("./uninative.so", "addLibrary")
# allow arbitrary C functions, marshalled by a small piece of assembler
native := loadfunc("./uninative.so", "native")
# add the testing functions to the dlsym search path,
# the handle is somewhat irrelevant, but won't be soonish
dlHandle := addLibrary("./cobolnative.so")
# initialize GnuCOBOL
native("cob_init", TYPEVOID)
# pass two integers, get back a sum
ans := native("sample", TYPEINT, 40, 2)
write("Unicon: called sample and got ", ans)
# rundown the libcob runtime
native("cob_tidy", TYPEVOID)
end
Result pass
prompt$ cobc -m cobolnative.cob
prompt$ unicon -s testcob.icn -x
GnuCOBOL got +0000000040, +0000000002
Unicon: called sample and got 42
Sad part, the inline assembly is only x86_64 System V ABI at the moment. (about 70 lines of inline extended assembler code, some 17 instructions, to manage both integral and double sized reals, input (freely mixed types) and return). That code needs to change to handle floats (versus double) another 17 instructions, without any refactoring. At this point in time, a single function can't have mixed C float and double data, all other type mixes are testing well, but this is only a few hours in to the experiments. Somewhat cherry picked testing, but integer, pointer/handle, real, and string data is functional. There will be edge cases to find and work out, and details regarding memory ownership and the like. This builds on the existing loadfunc feature but most details are then managed by a single entry point, "native(...)".
Windows 64 and 32 and other operating environments should be in the same range of instruction counts, but I'll know a little more once 32bit GNU/Linux is tackled, with the different call frame rules. It might be upwards of 30 instructions that need to be hand coded, not an overly burdensome burden for the powers that it provides to Unicon, in my biased opinion. No wrappers required to get at C library functions.
Jafar, Clinton; I need a little education on the new mkExternal feature in icall.h, as I could not get a working sample. Currently, pointer data is just sent back as an integer handle (which will break on some platforms), and I'd like to extend the supported types to C structs and pointers to memory blocks, etc. I hope that just a short working example on what the actual C data type declaration is to start running with it; could not tell from the macro, so I thought I'd just ask instead of flailing about.
More at https://sourceforge.net/p/unicon/discussion/contributions/thread/4f3103fc/ (https://sourceforge.net/p/unicon/discussion/contributions/thread/4f3103fc/)
And an initial usage sample that embeds libharu for PDF generation at
https://sourceforge.net/p/unicon/discussion/general/thread/5e5d4ab1/ (https://sourceforge.net/p/unicon/discussion/general/thread/5e5d4ab1/)
If this seems like a want-able thing by the Unicon community, it'll require a small piece of assembler for each platform that wants to take part. Getting cross-platform, by writing to each platform. ;-) If that happens, there will be a call out for volunteers that have access to various C compiler versions and OS releases on various chipsets. Expect less than a page of code per platform.
Have good, make well, happiest of 2017s,
Brian
Tests are working out well with (a very platform specific) inline assembly layer.
The test COBOL
identification division.
program-id. sample.
data division.
linkage section.
01 one usage binary-long.
01 two usage binary-long.
procedure division using by value one two.
sample-main.
display "GnuCOBOL got " one ", " two
compute return-code = one + two
goback.
end program sample.
And the test Unicon
#
# testcob.icn, test calling COBOL without wrapper
#
$include "natives.inc"
procedure main()
# will be RTLD_LAZY | RTLD_GLOBAL (so add to the search path)
addLibrary := loadfunc("./uninative.so", "addLibrary")
# allow arbitrary C functions, marshalled by a small piece of assembler
native := loadfunc("./uninative.so", "native")
# add the testing functions to the dlsym search path,
# the handle is somewhat irrelevant, but won't be soonish
dlHandle := addLibrary("./cobolnative.so")
# initialize GnuCOBOL
native("cob_init", TYPEVOID)
# pass two integers, get back a sum
ans := native("sample", TYPEINT, 40, 2)
write("Unicon: called sample and got ", ans)
# rundown the libcob runtime
native("cob_tidy", TYPEVOID)
end
Result pass
prompt$ cobc -m cobolnative.cob
prompt$ unicon -s testcob.icn -x
GnuCOBOL got +0000000040, +0000000002
Unicon: called sample and got 42
Sad part, the inline assembly is only x86_64 System V ABI at the moment. (about 70 lines of inline extended assembler code, some 17 instructions, to manage both integral and double sized reals, input (freely mixed types) and return). That code needs to change to handle floats (versus double) another 17 instructions, without any refactoring. At this point in time, a single function can't have mixed C float and double data, all other type mixes are testing well, but this is only a few hours in to the experiments. Somewhat cherry picked testing, but integer, pointer/handle, real, and string data is functional. There will be edge cases to find and work out, and details regarding memory ownership and the like. This builds on the existing loadfunc feature but most details are then managed by a single entry point, "native(...)".
Windows 64 and 32 and other operating environments should be in the same range of instruction counts, but I'll know a little more once 32bit GNU/Linux is tackled, with the different call frame rules. It might be upwards of 30 instructions that need to be hand coded, not an overly burdensome burden for the powers that it provides to Unicon, in my biased opinion. No wrappers required to get at C library functions.
Jafar, Clinton; I need a little education on the new mkExternal feature in icall.h, as I could not get a working sample. Currently, pointer data is just sent back as an integer handle (which will break on some platforms), and I'd like to extend the supported types to C structs and pointers to memory blocks, etc. I hope that just a short working example on what the actual C data type declaration is to start running with it; could not tell from the macro, so I thought I'd just ask instead of flailing about.
More at https://sourceforge.net/p/unicon/discussion/contributions/thread/4f3103fc/ (https://sourceforge.net/p/unicon/discussion/contributions/thread/4f3103fc/)
And an initial usage sample that embeds libharu for PDF generation at
https://sourceforge.net/p/unicon/discussion/general/thread/5e5d4ab1/ (https://sourceforge.net/p/unicon/discussion/general/thread/5e5d4ab1/)
If this seems like a want-able thing by the Unicon community, it'll require a small piece of assembler for each platform that wants to take part. Getting cross-platform, by writing to each platform. ;-) If that happens, there will be a call out for volunteers that have access to various C compiler versions and OS releases on various chipsets. Expect less than a page of code per platform.
Have good, make well, happiest of 2017s,
Brian