March 21, 2006
In article <dvp95v$krm$1@digitaldaemon.com>, NoBoDy says...
>
>VB6 internally stores strings in UNICODE.
>When calling external functions VB6 uses stub to convert string to/from ANSI
>format.
>
>If you want to pass string from VB in Unicode use declaration like this: Declare Function findChar Lib "..." (ByVal t As LONG) As Long
>
>and call that function as:
>retValue = findChar(StrPtr("Some string"))
>
>this will pass pointer to UNICODE string to externall function findChar
>

Now that I hadn't seen before. If I can get it to work, it will solve a whole bunch of problems. Thanks.

Rory


March 21, 2006
How do I join this newsgroupd if that is what this is? What do I use for NNTP?


March 21, 2006
Rory Starkweather wrote:
>>Actually you want to use wchar* at the D end from VB.  VB sends 'Unicode' strings where each character is represented by two bytes. This is the equivalent of a wchar* in D.  char, wchar, and dchar in D are all more-or-less interchangeable.  The best way to get VB and D to do string work together is this:
>>
>>Declare Function findChar Lib "..." (ByVal t As String) As Long
>>
>>export extern (Windows) int findChar(wchar* str) {
>>	...
> 
> 
>>I'm not 100% sure if this works as I've had serious issues with VB6's string handling in the past (especially in scenarios like this).  I think the trick is to initialize the string from VB's side and pass it in to C/C++/D for them to modify it.  I'll do some more research on this and get you a better answer if I can.
>>
> 
> 
> I may be running into that now. I decided to forget about the dchar issue and
> use another version of find: find (char[] s, char[] sub)
> 
> I don't get any compile errors or nasty comments from VB, but the value I get
> back indicates that the character is not in the strin (-1)
> 
> ************************** Here's the VB stuff
> 
> Public Declare Function findACharInString _
> Lib "E:\DigitalMars\Work\DInStr.dll" _
> (ByRef strString As String, _
> ByRef strSearchChar As String) _
> As Long
> 
> Private Sub cmdTest1_Click()
> 
> Dim lngCharPointer As Long
> Dim strString As String
> Dim strChar As String * 1
> 
> strString = "Fred"
> strChar = "e"
> 
> lngCharPointer = findACharInString(strString, strChar)
> 
> MsgBox strChar & " found at " & CStr(lngCharPointer)
> 
> End Sub
> 
> ******************************* Here's the D code:
> 
> //--------DInStr.d-----------
> import DLLMain;
> import std.string;      // For find
> 
> extern (Windows)
> {
> int findACharInString(char* searchString, char* searchChar)
> {
> int iPointer = 0;
> char[] theChar;
> char[] theString;
> 
> theString = std.string.toString(searchString);
> theChar = std.string.toString(searchChar);
> 
> iPointer = find(theString, theChar);
> 
> return (iPointer);
> }
> }

I think we've discovered in another reply thread that the source of the error is the use of char* instead of wchar* and the missing StrPtr() call on the VB side.  Learn something new every day!

> 
> I figured that the string and the character might not look the same after they
> were massaged, so I added this:
> 
> void main(char[][] Args)
> {
> int iRetVal;
> 
> iRetVal = findACharInString(Args[1], Args[2]);
> 
> printf("%s found at %d\n", Args[2], iRetVal);
> }
> 

Well, the error here (I would assume) is your use of %s instead of %.*s, yes arcane printf knowledge to the rescue again.

> That just causes more problems. When I try to run it I get an Access Violation.
> (?) I can't find that note on the caveat for printf and strings, so I assume I'm
> running into that problem here. I originally tried using writefln in
> findACharInString and consistently got "Unknown software exception (0xe0440001)
> occurred in app at location 0x7c59bc3f. (I was surprised that it was so
> consistent.) So I must not understand that function either.
> 
> I think the way I tried to do it looked like this:
> 
> writefln("The string: %s", theString);
> writefln("The character: %s", theChar);
> 

Wondering why this didn't work...

> Its amazing that so many things can go wrong with a program that is only 7 lines
> long. Part of the problem is that it has been 10 years since I have used C, and
> I have never used D before this week. There seems to be a hump in learning "new"
> programming languages. One day nothing works the first ten times and the next
> day about half of what you write works the first time. I'm not at that point
> yet.
> 
> Rory
> 
> 
> Aggressively seeking arcane knowledge.

It's the best kinda knowledge out there!  Try looking up Sound Blaster 16 and VGA interrupts and output ports - that's some fun arcane knowledge.

-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O M--@ V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++
------END GEEK CODE BLOCK------

James Dunne
March 21, 2006
Rory Starkweather wrote:

> How do I join this newsgroupd if that is what this is? What do I use for NNTP?

You use a NNTP-client ;) Most modern email-readers have one. Windows-users seems to prefer Thunderbird, although Outlook Express work. It should be fairly easy process:

Add an News-account (similar to email account) for the news.digitalmars.com server. Then you can search that server for groups, and you "subscribe" to those you're interested in. Posting and reading is then almost like reading/writing email.
March 21, 2006
Thanks. It was as easy as you said.


March 21, 2006
> 
> 
> I think we've discovered in another reply thread that the source of the error is the use of char* instead of wchar* and the missing StrPtr() call on the VB side.  Learn something new every day!
> 

 StrPtr() call? You're just saying that its unfortunate that VB doesn't have any civilized programming constructs aren't you? I have to admit that I have learned about three VB functions I had never heard of during the last few weeks. VB Help is of limited usefulness in finding things like that, unless I am also doing that incorrectly.

 I did make the change to wchar*. I'll try that too.

>>
> Well, the error here (I would assume) is your use of %s instead of %.*s, yes arcane printf knowledge to the rescue again.
>

 I have made the change. I'll try it in a few minutes.

>>
>> writefln("The string: %s", theString);
>> writefln("The character: %s", theChar);
>>
> 
> Wondering why this didn't work...
> 
 I probably fat-fingered something.
March 21, 2006
Correct me on this if I am wrong:

UNICODE is *not* an _encoding_ standard; it is a standard mapping of character glyphs to integer values and specifies no requirements for storage or encoding.

The encoding to which you (and many others) refer to by the name of UNICODE is in fact UCS-2, I believe.  This is the encoding where the Basic Multilingual Plane (BMP) of the Unicode table maps directly onto 65536 values.

NoBoDy wrote:
> VB6 internally stores strings in UNICODE.
> When calling external functions VB6 uses stub to convert string to/from ANSI
> format.
> 
> If you want to pass string from VB in Unicode use declaration like this:
> Declare Function findChar Lib "..." (ByVal t As LONG) As Long
> 
> and call that function as:
> retValue = findChar(StrPtr("Some string"))
> 
> this will pass pointer to UNICODE string to externall function findChar
> 
> 
> In article <dvp71g$hv1$1@digitaldaemon.com>, James Dunne says...
> 
>>Rory Starkweather wrote:
>>
>>>>void foo(dchar c) {}
>>>>void main()
>>>>{
>>>>	foo('a');
>>>>}
>>>>
>>>>so you'll probably have no trouble there. :)
>>>>
>>>
>>>
>>>
>>>Thanks for the help. I'm still not sure how to get VB to send a dchar, but there
>>>are only a couple of possibilities. Unless you are suggesting that I pass it to
>>>D as a string and then use a conversion function on it.
>>>
>>>
>>
>>Actually you want to use wchar* at the D end from VB.  VB sends 'Unicode' strings where each character is represented by two bytes. This is the equivalent of a wchar* in D.  char, wchar, and dchar in D are all more-or-less interchangeable.  The best way to get VB and D to do string work together is this:
>>
>>Declare Function findChar Lib "..." (ByVal t As String) As Long
>>
>>export extern (Windows) int findChar(wchar* str) {
>>	...
>>}
>>
>>I'm not 100% sure if this works as I've had serious issues with VB6's string handling in the past (especially in scenarios like this).  I think the trick is to initialize the string from VB's side and pass it in to C/C++/D for them to modify it.  I'll do some more research on this and get you a better answer if I can.
>>
>>-- 
>>-----BEGIN GEEK CODE BLOCK-----
>>Version: 3.1
>>GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O M--@ V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++
>>------END GEEK CODE BLOCK------
>>
>>James Dunne
> 
> 
> 


-- 
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/MU/S d-pu s:+ a-->? C++++$ UL+++ P--- L+++ !E W-- N++ o? K? w--- O M--@ V? PS PE Y+ PGP- t+ 5 X+ !R tv-->!tv b- DI++(+) D++ G e++>e h>--->++ r+++ y+++
------END GEEK CODE BLOCK------

James Dunne
March 21, 2006
James Dunne wrote:
> Correct me on this if I am wrong:
> 
> UNICODE is *not* an _encoding_ standard; it is a standard mapping of character glyphs to integer values and specifies no requirements for storage or encoding.

Well, since you asked - it's not glyphs, but characters :)

http://en.wikipedia.org/wiki/Glyph

> The encoding to which you (and many others) refer to by the name of UNICODE is in fact UCS-2, I believe.  This is the encoding where the Basic Multilingual Plane (BMP) of the Unicode table maps directly onto 65536 values.
And here it's more complicated. UCS-2 is exactly what you say, but AFAIK D uses UTF-16 and so does Windows:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/intl/unicode_9i79.asp

They're almost the same, except UTF-16 allows surrogate pairs for encoding other character planes, while UCS-2 doesn't. I think UCS-2 is somewhat deprecated generally, exactly because of this reason.


xs0
March 21, 2006
I'm totally lost now. The DLL version didn't like the wchar* types and it wouldn't compile. So I tried the command line version. It not only compiled, it worked perfectly. (Except for tht nasty and long forgotten 0 based things.)

So I copied the command line version over the DLL version and I get:

e:\DigitalMars\DMD\Bin\..\..\dm\bin\link.exe dinstr,,,user32+kernel32/noi;

OPTLINK (R) for Win32  Release 7.50B1
Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved

OPTLINK : Warning 23: No Stack
dinstr.obj(dinstr)
 Error 42: Symbol Undefined __nullext
dinstr.obj(dinstr)
 Error 42: Symbol Undefined __ModuleInfo_3std6string
OPTLINK : Warning 134: No Start Address
--- errorlevel 2

I can't see a difference between what is in DInStr.d now and the code below that was posted before any changes. The new version is posted below the >> version, which is from an earlier message at a time when it compiled OK, but didn't work.

>> ******************************* Here's the ** OLD *** D code:
>>
>> //--------DInStr.d-----------
>> import DLLMain;
>> import std.string;      // For find
>>
>> extern (Windows)
>> {
>> int findACharInString(char* searchString, char* searchChar)
>> {
>> int iPointer = 0;
>> char[] theChar;
>> char[] theString;
>>
>> theString = std.string.toString(searchString);
>> theChar = std.string.toString(searchChar);
>>
>> iPointer = find(theString, theChar);
>>
>> return (iPointer);
>> }
>> }

******************************* Here's the ** NEW *** D code:
//--------DInStr.d-----------
import DLLMain;
import std.string;      // For find

extern (Windows)
{
 int findACharInString(char* searchString, char* searchChar)
 {
    int iPointer = 0;
    char[] theChar;
    char[] theString;

    theString = std.string.toString(searchString);
    theChar = std.string.toString(searchChar);

    iPointer = find(theString, theChar);

   return (iPointer);
  }
}

As I said, I can't see the difference.

To confuse the issue even further, here's the commandline version, that works perfectly. I realize that I am passing char[] to findACharInString in this version but I don't see why it compiles without a hitch.

Command line used: DInstrCL Fred e

//--------DInStrCL.d-----------
import DLLMain;
import std.string;      // For find

extern (Windows)
{
 int findACharInString(char* searchString, char* searchChar)
 {
    int iPointer = 0;
    char[] theChar;
    char[] theString;

    theString = std.string.toString(searchString);
    theChar = std.string.toString(searchChar);

    iPointer = find(theString, theChar);

   return (iPointer);
  }
}

void main(char[][] Args)
{
    int iRetVal;

    iRetVal = findACharInString(Args[1], Args[2]);

    printf("%.*s found at %d\n", Args[2], iRetVal);
}
March 22, 2006
Rory Starkweather wrote:
> I'm totally lost now. The DLL version didn't like the wchar* types and it wouldn't compile. So I tried the command line version. It not only compiled, it worked perfectly. (Except for tht nasty and long forgotten 0 based things.)
> 
> So I copied the command line version over the DLL version and I get:
> 
> e:\DigitalMars\DMD\Bin\..\..\dm\bin\link.exe dinstr,,,user32+kernel32/noi;
> 
> OPTLINK (R) for Win32  Release 7.50B1
> Copyright (C) Digital Mars 1989 - 2001  All Rights Reserved
> 
> OPTLINK : Warning 23: No Stack
> dinstr.obj(dinstr)
>  Error 42: Symbol Undefined __nullext
> dinstr.obj(dinstr)
>  Error 42: Symbol Undefined __ModuleInfo_3std6string
> OPTLINK : Warning 134: No Start Address
> --- errorlevel 2
> 
> I can't see a difference between what is in DInStr.d now and the code below that was posted before any changes. The new version is posted below the >> version, which is from an earlier message at a time when it compiled OK, but didn't work.
> 
>>> ******************************* Here's the ** OLD *** D code:
>>>
>>> //--------DInStr.d-----------
>>> import DLLMain;
>>> import std.string;      // For find
>>>
>>> extern (Windows)
>>> {
>>> int findACharInString(char* searchString, char* searchChar)
>>> {
>>> int iPointer = 0;
>>> char[] theChar;
>>> char[] theString;
>>>
>>> theString = std.string.toString(searchString);
>>> theChar = std.string.toString(searchChar);
>>>
>>> iPointer = find(theString, theChar);
>>>
>>> return (iPointer);
>>> }
>>> }
> 
> 
> ******************************* Here's the ** NEW *** D code:
> //--------DInStr.d-----------
> import DLLMain;
> import std.string;      // For find
> 
> extern (Windows)
> {
>  int findACharInString(char* searchString, char* searchChar)
>  {
>     int iPointer = 0;
>     char[] theChar;
>     char[] theString;
> 
>     theString = std.string.toString(searchString);
>     theChar = std.string.toString(searchChar);
> 
>     iPointer = find(theString, theChar);
> 
>    return (iPointer);
>   }
> }
> 
> As I said, I can't see the difference.
> 
> To confuse the issue even further, here's the commandline version, that works perfectly. I realize that I am passing char[] to findACharInString in this version but I don't see why it compiles without a hitch.
> 
> Command line used: DInstrCL Fred e
> 
> //--------DInStrCL.d-----------
> import DLLMain;
> import std.string;      // For find
> 
> extern (Windows)
> {
>  int findACharInString(char* searchString, char* searchChar)
>  {
>     int iPointer = 0;
>     char[] theChar;
>     char[] theString;
> 
>     theString = std.string.toString(searchString);
>     theChar = std.string.toString(searchChar);
> 
>     iPointer = find(theString, theChar);
> 
>    return (iPointer);
>   }
> }
> 
> void main(char[][] Args)
> {
>     int iRetVal;
> 
>     iRetVal = findACharInString(Args[1], Args[2]);
> 
>     printf("%.*s found at %d\n", Args[2], iRetVal);
> }

As much as I'd love to help you out, I'm also hopelessly lost.  Can you ZIP up your project and document your test cases and post them on the NG or e-mail them to me personally?  The e-mail I post with on the newsgroups is my valid e-mail.

-- 
Regards,
James Dunne