Perl Win32::API() call() function - perl

Dear all,
I am trying to get the value of char pointer or string in the return of call() function for my dll.
my dll is having a function RandomDec(long , int*) and returns a string. so what will be my call using Win32::API(). I have tried this and didn't succeed. plz help
use Win32::API;
my #lpBuffer = " " x 20;
my $pp= \#lpBuffer;
my $xy=0;
my $ff= \$xy;
my $fun2 = new Win32::API('my.dll','RandomDec','NP','**P**')or die $^E;
$pp = $fun2->Call(4,$ff);
how to get using $pp ?

There are multiple errors in your code.
my #lpBuffer = " " x 20; my $pp= \#lpBuffer;
=> my $pp = " " x 20;
You are mixing arrays with strings, and you don't need a perl ref for a c ptr.
Similar for the int*.
N is for number not long. L would be unsigned, you need signed, so l.
use Win32::API;
my $pp = " " x 20; # alloc a string
my $xy = 0; # alloc an int
my $fun2 = new Win32::API('my.dll','RandomDec','lP','P') or die $^E;
$pp = $fun2->Call(4,$xy);
I haven't check if Win32::API can do lvalue assignment to char*. Normally not, so $pp will be a foreign pointer to some string after the call, and the prev. PV slot for $pp will be lost, and inaccessible from perl.
With FFI's and the WinAPI also you usually return int, not strings.
Strings only via sideeffects, as function arg.

Related

Are unsigned long types available to LibreOffice Basic?

I'm want to write a simple 32-bit FNV hash function for LibreOffice Calc. However, LibreOffice Basic only supports signed long data types, so you will get an "Inadmissible value or data type. Overflow." error on line 7 with the following code:
Function Hash(strText as String) as Long
Dim h As Long
Dim nextChar As String
Dim temp As Long
h = 2166136261
For i = 1 To Len(strText)
nextChar = Mid(strText, i, 1)
temp = Asc(nextChar)
h = h XOR temp
h = h * 16777619
Next
Hash = h
End Function
Because the h variable is assigned 2166136261 in the code above, it is obviously out of bounds. Is it possible to work with unsigned long (0 to 4294967295) data types in LibreOffice Basic? If so, how?
You could do this:
Sub CallHash
oMasterScriptProviderFactory = createUnoService(_
"com.sun.star.script.provider.MasterScriptProviderFactory")
oScriptProvider = oMasterScriptProviderFactory.createScriptProvider("")
oScript = oScriptProvider.getScript(_
"vnd.sun.star.script:foo.py$hash?language=Python&location=user")
hashString = oScript.invoke(Array("bar"), Array(), Array())
MsgBox hashString
End Sub
foo.py:
def hash(strText):
h = 2166136261
for nextChar in strText:
temp = ord(nextChar)
h = h ^ temp
h = h * 16777619
return str(h)
Or drop Basic and use only Python-UNO.
There are unsigned long values in the UNO API. However, I didn't find any API methods to perform calculations on this object.
Dim o As Object
o = CreateUnoValue("unsigned long", 2166136261)

For colon operator with char operands, first and last operands must be char

I have a Matlab code as you can see here :
function IWDalg(similarityMatrix,NumberOfSentencesInFile,NumberOfSentencesInAbstract)
NumIWDs = str2int(NumberOfSentencesInFile);
Numnodes=NumIWDs;
av = 1; bv = 0.01; cv = 1;
as = 1; bs = 0.01; cs = 1;
soil = repmat(InitSoil,Numnodes,Numnodes);
for i =1:NumIWDs
IWD{i}.vel = InitVel;
IWD{i}.tour = [];
IWD{i}.tour(1) =i;
IWD{i}.soil = 0;
end
I the loop for when the matlab tries to compile first line of For clause i got this error:
??? For colon operator with char operands, first and last operands must be char.
I am so beginner in matlab programming .
Best regards
Try this .
NumIWDs = str2double(NumberOfSentencesInFile);
You should convert char to double for executing for colon.

What is RMAGICAL?

I'm trying to understand some XS code that I inherited. I've been trying to add comments to a section that invokes Perl magic stuff, but I can't find any documentation to help me understand this line:
SvRMAGICAL_off((SV *) myVar);
What is RMAGICAL for? When should one turn in on or off when working with Perl magic variables?
Update
Perlguts Illustrated is very interesting and has a little bit of info on RMAGICAL (the 'R' is for 'random'), but it doesn't say when to mess with it: http://cpansearch.perl.org/src/RURBAN/illguts-0.42/index.html
It's a flag that indicates whether a variable has "clear" magic, magic that should be called when the variable is cleared (e.g. when it's destroyed). It's used by mg_clear which is called when one attempts to do something like
undef %hash;
delete $a[4];
etc
It's derived information calculated by mg_magical that should never be touched. mg_magical will be called to update the flag when magic is added to or removed from a variable. If any of the magic attached to the scalar has a "clear" handler in its Magic Virtual Table, the scalar gets RMAGICAL set. Otherwise, it gets turned off. Effectively, this caches the information to save Perl from repeatedly checking all the magic attached to a scalar for this information.
One example use of clear magic: When a %SIG entry is cleared, the magic removes the signal handler for that signal.
Here's mg_magical:
void
Perl_mg_magical(pTHX_ SV *sv)
{
const MAGIC* mg;
PERL_ARGS_ASSERT_MG_MAGICAL;
PERL_UNUSED_CONTEXT;
SvMAGICAL_off(sv);
if ((mg = SvMAGIC(sv))) {
do {
const MGVTBL* const vtbl = mg->mg_virtual;
if (vtbl) {
if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP))
SvGMAGICAL_on(sv);
if (vtbl->svt_set)
SvSMAGICAL_on(sv);
if (vtbl->svt_clear)
SvRMAGICAL_on(sv);
}
} while ((mg = mg->mg_moremagic));
if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)))
SvRMAGICAL_on(sv);
}
}
The SVs_RMG flag (which is what SvRMAGICAL tests for and SvRMAGICAL_on/SvRMAGICAL_off sets/clears) means that the variable has some magic associated with it other than a magic getter method (which is indicated by the SVs_GMG flag) and magic setter method (indicated by SVs_SMG).
I'm getting out of my depth, here, but examples of variables where RMAGIC is on include most of the values in %ENV (the ones that are set when the program begins, but not ones you define at run-time), the values in %! and %SIG, and stash values for named subroutines (i.e., in the program
package main;
sub foo { 42 }
$::{"foo"} is RMAGICAL and $::{"bar"} is not). Using Devel::Peek is a little bit, but not totally enlightening about what this magic might be:
$ /usr/bin/perl -MDevel::Peek -e 'Dump $ENV{HOSTNAME}'
SV = PVMG(0x8003e910) at 0x800715f0
REFCNT = 1
FLAGS = (SMG,RMG,POK,pPOK)
IV = 0
NV = 0
PV = 0x80072790 "localhost"\0
CUR = 10
LEN = 12
MAGIC = 0x800727a0
MG_VIRTUAL = &PL_vtbl_envelem
MG_TYPE = PERL_MAGIC_envelem(e)
MG_LEN = 8
MG_PTR = 0x800727c0 "HOSTNAME"
Here we see that the scalar held in $ENV{HOSTNAME} has an MG_TYPE and MG_VIRTUAL that give you the what, but not the how and why of this variable's magic. On a "regular" magical variable, these are usually (always?) PERL_MAGIC_sv and &PL_vtbl_sv:
$ /usr/bin/perl -MDevel::Peek -e 'Dump $='
SV = PVMG(0x8008e080) at 0x80071de8
REFCNT = 1
FLAGS = (GMG,SMG)
IV = 0
NV = 0
PV = 0
MAGIC = 0x80085aa8
MG_VIRTUAL = &PL_vtbl_sv
MG_TYPE = PERL_MAGIC_sv(\0)
MG_OBJ = 0x80071d58
MG_LEN = 1
MG_PTR = 0x80081ad0 "="
There is one place in the perl source where SvRMAGICAL_off is used -- in perlio.c, in the XS(XS_io_MODIFY_SCALAR_ATTRIBUTES).
XS(XS_io_MODIFY_SCALAR_ATTRIBUTES)
{
dXSARGS;
SV * const sv = SvRV(ST(1));
AV * const av = newAV();
MAGIC *mg;
int count = 0;
int i;
sv_magic(sv, MUTABLE_SV(av), PERL_MAGIC_ext, NULL, 0);
SvRMAGICAL_off(sv);
mg = mg_find(sv, PERL_MAGIC_ext);
mg->mg_virtual = &perlio_vtab;
mg_magical(sv);
Perl_warn(aTHX_ "attrib %" SVf, SVfARG(sv));
for (i = 2; i < items; i++) {
STRLEN len;
const char * const name = SvPV_const(ST(i), len);
SV * const layer = PerlIO_find_layer(aTHX_ name, len, 1);
if (layer) {
av_push(av, SvREFCNT_inc_simple_NN(layer));
}
else {
ST(count) = ST(i);
count++;
}
}
SvREFCNT_dec(av);
XSRETURN(count);
}
where for some reason (again, I'm out of my depth), they want that magic turned off during the mg_find call.

genstrings does not work with macro for NSLocalizedString

I would like to shorten "NSLocalizedString" to "_" so I'm using macro
_(x) NSLocalizedString(#x, #__FILE__)
.
But now, when I want to generate strings for localization with
find . -name \*.m | xargs genstrings
it generates nothing.
Any help?
You can tell genstrings to look for a different function by using the '-s' argument:
genstring -s MyFunctionName ....
However, MyFunctionName must follow the same naming and argument conventions as one of the built in NSLocalizeString macros.
In your case, you can not just specify the string key, you must also specify the documentation string. In fact, you should never generate a strings file without both the string and documentation. There are many languages where the actual phrase or word will depend on context. German is a great example where a car is "das auto" and more than one is "die autos". There are many more examples that include changes for gender, number, time, question versus statement, and yes versus no. The documentation string helps your translator figure out what translation to use.
In addition, the best practice is to use a key that is different from the native language word. That says use NSLocalizedStringWithDefaultValue(key, table, bundle, val, comment).
You can specify nil for the table and [NSBundle mainBundle] for the bundle argument.
You can wrap this in a shorthand, but you still have to follow the StringWithDefaultValue name and the arguments for genstrings to work.
I strongly recommend you look at the WWDC 2012 session on Localization Tips and Tricks.
Maurice
You can use the -s option of genstrings. From the man page :
-s routine
Substitutes routine for NSLocalizedString. For example, -s MyLocalString will catch calls to MyLocalString and MyLocalStringFromTable.
So I think you could try :
genstrings -s _
I had the same problem when my NSLocalizedString macro was taking 1 argument instead of 2 like genstrings expects, so i wrote i python script that does the job.
the first argument for the script is the macro name and the second is the path to your project.
import fnmatch
import os
from xml.dom import minidom
function = sys.argv[1]
rootdir = sys.argv[2]
# Generate strings from .m files
files = []
for root, dirnames, filenames in os.walk(rootdir):
for filename in fnmatch.filter(filenames, '*.m'):
files.append(os.path.join(root, filename))
strings = []
for file in files:
lineNumber = 0
for line in open(file):
lineNumber += 1
index = line.find(function)
if (index != -1):
callStr = line[index:]
index = callStr.find('#')
if (index == -1):
print 'call with a variable/macro. file: ' + file + ' line: %d' % lineNumber
else:
callStr = callStr[index+1:]
index = callStr.find('")')
callStr = callStr[:index+1]
if callStr not in strings:
strings.append(callStr)
# Write strings to file
f = open('Localizable.strings', 'w+')
for string in strings:
f.write(string + ' = ' + string + ';\n\n')
f.close()
I have improved Or Arbel's script to include the cases where there's multiple macro-calls on a single line:
import fnmatch
import os
from xml.dom import minidom
import sys
function = sys.argv[1]
rootdir = sys.argv[2]
# Generate strings from .m files
files = []
for root, dirnames, filenames in os.walk(rootdir):
for filename in fnmatch.filter(filenames, '*.m'):
files.append(os.path.join(root, filename))
strings = []
for file in files:
lineNumber = 0
for line in open(file):
lineNumber += 1
index = line.find(function)
startIndex = 0
while (index != -1):
startIndex = index+1
callStr = line[index:]
index = callStr.find('#')
if (index == -1):
print 'call with a variable/macro. file: ' + file + ' line: %d' % lineNumber
else:
callStr = callStr[index+1:]
index = callStr.find('")')
callStr = callStr[:index+1]
if callStr not in strings:
strings.append(callStr)
index = line.find(function, startIndex)
# Write strings to file
f = open('Localizable.strings', 'w+')
for string in strings:
f.write(string + ' = ' + string + ';\n\n')
f.close()

Moving binary data to/from Perl using SWIG

I'm trying to make it easy for me to move binary data between Perl and my C++ library.
I created a c++ struct to hand the binary_data:
struct binary_data {
unsigned long length;
unsigned char *data;
};
In my SWIG interface file for I have the following:
%typemap(in) binary_data * (binary_data temp) {
STRLEN len;
unsigned char *outPtr;
if(!SvPOK($input))
croak("argument must be a scalar string");
outPtr = (unsigned char*) SvPV($input, len);
printf("set binary_data '%s' [%d] (0x%X)\n", outPtr, len, $input);
temp.data = outPtr;
temp.length = len;
$1 = &temp;
}
%typemap(out) binary_data * {
SV *obj = sv_newmortal();
if ($1 != 0 && $1->data != 0 && $1->length > 0) {
sv_setpvn(obj, (const char*) $1->data, $1->length);
printf("get binary_data '%s' [%d] (0x%X)\n", $1->data, $1->length, obj);
} else {
sv_setsv(obj, &PL_sv_undef);
printf("get binary_data [set to undef]\n");
}
if( !SvPOK(obj) )
croak("The result is not a scalar string");
$result = obj;
}
I build my Perl module via "ExtUtils::MakeMaker" and it's all good.
I then run the following perl test script to ensure the binary data is being
set/get from a perl string correctly.
my $fr = ObjectThatContainsBinaryData->new();
my $data = "1234567890";
print ">>>PERL:swig_data_set\n";
$fr->swig_data_set($data);
print "<<<PERL:swig_data_set\n";
print ">>>PERL:swig_data_get\n";
my $rdata = $fr->swig_data_get();
print "<<<PERL: swig_data_get\n";
print "sent :" . \$data . " len=" . length($data). " '$data'\n"
."recieved:". \$rdata. " len=" . length($rdata). " '$rdata'\n";
Now the combined C++ and Perl printf stdout is:
>>>PERL:swig_data_set
set binary_data '1234567890' [10] (0x12B204D0)
<<<PERL:swig_data_set
>>>PERL:swig_data_get
get binary_data '1234567890' [10] (0x1298E4E0)
<<<PERL: swig_data_get
sent :SCALAR(0x12b204d0) len=10 '1234567890'
recieved:SCALAR(0x12bc71c0) len=0 ''
So why does it look like the perl call to sv_setpvn is failing or not working?
I don't know why when I print the returned binary data in perl, it shows as an empty scalar, but it looks fine within the SWIG C++ embedded typemap.
I'm using:
Perl v5.8.8 built for x86_64-linux-thread-multi
SWIG 2.0.1
gcc version 4.1.1 20070105 (Red Hat 4.1.1-52)
If you replace the following line of in your %typemap(out):
$result = obj;
With
$result = obj; argvi++; //This is a hack to get the hidden stack pointer to increment before the return
The SWIG Generated code will now look like:
...
ST(argvi) = obj; argvi++;
}
XSRETURN(argvi);
}
And your test script will return the Perl String as expected.
SV = PV(0x1eae7d40) at 0x1eac64d0
REFCNT = 1
FLAGS = (PADBUSY,PADMY,POK,pPOK)
PV = 0x1eb25870 "1234567890"\0
CUR = 10
LEN = 16
<<<PERL: swig_data_get
sent :SCALAR(0x1ea64530) len=10 '1234567890'
recieved:SCALAR(0x1eac64d0) len=10 '1234567890'
You should have read the SWIG 2.0 documentation on typemaps in Perl more closely:
"
30.8.2 Return values
Return values are placed on the argument stack of each wrapper function. The current value of the argument stack pointer is contained in a variable argvi. Whenever a new output value is added, it is critical that this value be incremented. For multiple output values, the final value of argvi should be the total number of output values.
"
What if you don't make it mortal? I was doing testing with Inline::C (since I've never used SWIG), and setting the SV to mortal caused problems since Inline::C was doing it for me. Perhaps SWIG uses a similar design?
Both
SV* obj = newSV(0);
sv_setpvn(obj, "abc", 3);
and
SV* obj = newSVpvn("abc", 3);
worked with Inline::C.
swig provides a module named cdata.i.
You should include this in the interface definition file.
Once you include this, it gives two functions cdata() and memmove(). Given a void * and the length of the binary data, cdata() converts it into a string type of the target language.
memmove() is the reverse. given a string type, it will copy the contents of the string(including embedded null bytes) into the C void* type.
Handling binary data becomes much simple with this module.
I hope this is what you need.
On the Perl side, could you add
use Devel::Peek;
Dump($fr->swig_data_get());
and provide the output? Thanks.