Problem using C module in perl

Problem using C module in perl

am 05.01.2006 14:03:59 von roopa.tp

I am tying use C module in the Perl script using inlineC.
I want to get the data stored in the SV* to char*
Following is the code which I have written.But the data displayed is
not complete
=======================================
MultiByteToWideChar(CP_ACP,0,lpValueName,strlen(lpValueName) +1,(LPWSTR)&lpValueName_w,sizeof(lpValueName_w)
; // size of buffer
asc_data = SvPVX(lpData);
MultiByteToWideChar(CP_ACP,0,asc_data,strlen(asc_data)+1,(LP WSTR)&data,sizeof(data)
;
printf("Value name, data : %s - %s -%s\n", lpValueName, asc_data);

=========================================
But the problem is asc_data does not have the complete data.

Can you please let me know if the usage is correct.

Re: Problem using C module in perl

am 06.01.2006 03:51:06 von Sisyphus

wrote in message
news:1136466239.567789.110700@f14g2000cwb.googlegroups.com.. .
> I am tying use C module in the Perl script using inlineC.
> I want to get the data stored in the SV* to char*
> Following is the code which I have written.But the data displayed is
> not complete
> =======================================
>
MultiByteToWideChar(CP_ACP,0,lpValueName,strlen(lpValueName) +1,(LPWSTR)&lpVa
lueName_w,sizeof(lpValueName_w)
> ; // size of buffer
> asc_data = SvPVX(lpData);
>
MultiByteToWideChar(CP_ACP,0,asc_data,strlen(asc_data)+1,(LP WSTR)&data,sizeo
f(data)
> ;
> printf("Value name, data : %s - %s -%s\n", lpValueName, asc_data);
>
> =========================================
> But the problem is asc_data does not have the complete data.
>
> Can you please let me know if the usage is correct.
>

I gather you're dealing with wide characters ... and that could definitely
be relevant to the problem. I don't know how to correctly handle them. If
lpValueName and asc_data contain wide characters then I think printf() has a
specific modifier (but I don't know what it is) which you should use instead
of "%s". And if lpValueName contains wide characters you use wcslen()
instead of strlen().

It would probably be easier for us to help if you provided a complete but
*small* Inline::C script that demonstrated the problems you're facing.

However, here is some info that I hope will help

I think that SvPVX() copies the data only up until the first NULL char (\0)
that it finds. So if lpData contains one or more embedded NULL characters
then asc_data will stop at the first NULL it finds. You can avoid that
shortcoming by using SvPVx(sv, len), or SvPV(sv, len).

Similarly the "%s" modifier prints only up until the first NULL char - and
strlen() counts the number of characters up until the first NULL.

Not sure that this solves your problem, but it demonstrates some of the
issues:

use warnings;

use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

void foo1(SV * sv, int len) {
char *x;
int i;
x = SvPV(sv, len);
for(i = 0; i < len; ++i) printf("%c", x[i]); // proves it all got
copied
printf("\n%s\n%d\n", x, strlen(x)); // goes only as far as the first
NULL
}

EOC
$x = 'hello' . "\0" . 'world';

foo1($x, length($x));

Cheers,
Rob

Re: Problem using C module in perl

am 10.01.2006 17:58:06 von Ilya Zakharevich

[A complimentary Cc of this posting was sent to
Sisyphus
], who wrote in article <43bddb76$0$637$afc38c87@news.optusnet.com.au>:
> I think that SvPVX() copies the data only up until the first NULL char (\0)
> that it finds. So if lpData contains one or more embedded NULL characters
> then asc_data will stop at the first NULL it finds. You can avoid that
> shortcoming by using SvPVx(sv, len), or SvPV(sv, len).

SvPVX() (or SvPV(), etc) do not copy anything (at least for "normal"
SVs). What they return are just pointers to raw Perl buffers. (These
buffers may be in 8-bit or utf8 mode, distinguished by SV flags,
SvUTF8(sv).) So it is the user of SvPVX() who interprets the pointer.
It should be indeed ready to support embedded \0; this way SvPV() is
more convenient.

> Similarly the "%s" modifier prints only up until the first NULL char - and
> strlen() counts the number of characters up until the first NULL.

Number of bytes, not characters.

Anyway, one should use Perl string conversion functions, not some
random C function to convert between Perl formats. E.g., to have a
guaraantied utf8-format one should use SvPVutf8(sv,count). [count is
the number of *bytes* in the returned buffer.]

To convert to WideChar, one needs to know what WideChar is. If it is,
e.g., UTF-16native_endianness, there might a Perl builtin...

Hope this helps,
Ilya