www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - De-Referencing A Pointer

reply Rory Starkweather <Rory_member pathlink.com> writes:
Still working on a VB to D DLL interface. I want to pass a string to a D
function. The only way I have been able to do it without errors is ByRef on the
VB end, as expected, to a char* on the D end. However, I want to use the 'find'
function on the string. 'find' requires a char[] and a dchar as inputs. I
haven't been able to figure out how to de-reference the pointer for the char[]
and I don't know how to produce a dchar. 

Here's the code:

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

extern (Windows)
{
int findChar(char* searchString)
//int findChar(char[] searchString, dchar searchChar)
{
int iPointer = 0;
char[] eChar = "e";
char[] anotherString;

anotherString = *searchString; //<- Here's the problem

iPointer = find(anotherString, eChar);
// iPointer = find(*searchString, eChar);
// iPointer = find(&searchString, eChar);

return (iPointer);
}
}

The error message is "Cannot explicitly convert expression (*(searchString)) of
type char* to char[]. If I take out the '*' I get about the same thing.

The other problem is the dchar. What can I pass to the function that it will
think is a dchar?

Is there any documentation on this kind of thing? I haven't had much luck
interpreting the language specification.
Mar 20 2006
parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Rory Starkweather skrev:
 Still working on a VB to D DLL interface. I want to pass a string to a D
 function. The only way I have been able to do it without errors is ByRef on the
 VB end, as expected, to a char* on the D end. However, I want to use the 'find'
 function on the string. 'find' requires a char[] and a dchar as inputs. I
 I haven't been able to figure out how to de-reference the pointer for the
char[]
 and I don't know how to produce a dchar. 
a char* cStr is converted to char[] by cStr[0..std.c.string.strlen(cStr)] or std.string.toString(cStr) /Oskar
Mar 21 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 21 Mar 2006 09:00:15 +0100, Oskar Linde  
<oskar.lindeREM OVEgmail.com> wrote:
 Rory Starkweather skrev:
 Still working on a VB to D DLL interface. I want to pass a string to a D
 function. The only way I have been able to do it without errors is  
 ByRef on the
 VB end, as expected, to a char* on the D end. However, I want to use  
 the 'find'
 function on the string. 'find' requires a char[] and a dchar as inputs.  
 I
 I haven't been able to figure out how to de-reference the pointer for  
 the char[]
 and I don't know how to produce a dchar.
a char* cStr is converted to char[] by cStr[0..std.c.string.strlen(cStr)] or std.string.toString(cStr)
and you can get a dchar with std.utf.toUTF32(). Regan
Mar 21 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Tue, 21 Mar 2006 20:30:46 +1200, Regan Heath <regan netwin.co.nz> wrote:
 On Tue, 21 Mar 2006 09:00:15 +0100, Oskar Linde  
 <oskar.lindeREM OVEgmail.com> wrote:
 Rory Starkweather skrev:
 Still working on a VB to D DLL interface. I want to pass a string to a  
 D
 function. The only way I have been able to do it without errors is  
 ByRef on the
 VB end, as expected, to a char* on the D end. However, I want to use  
 the 'find'
 function on the string. 'find' requires a char[] and a dchar as  
 inputs. I
 I haven't been able to figure out how to de-reference the pointer for  
 the char[]
 and I don't know how to produce a dchar.
a char* cStr is converted to char[] by cStr[0..std.c.string.strlen(cStr)] or std.string.toString(cStr)
and you can get a dchar with std.utf.toUTF32().
Oops, I should read the whole post before replying. Any character literal will be accepted as a dchar, eg. void foo(dchar c) {} void main() { foo('a'); } so you'll probably have no trouble there. :) Regan
Mar 21 2006
parent reply Rory Starkweather <Rory_member pathlink.com> writes:
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.
Mar 21 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
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
Mar 21 2006
next sibling parent reply NoBoDy <NoBoDy_member pathlink.com> writes:
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
Mar 21 2006
next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
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
Thanks! That helps a lot for me as well. So then am I still correct in that D should work with a wchar* ? BTW, do you have an MSDN reference for that info? -- -----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
Mar 21 2006
parent "John C" <johnch_atms hotmail.com> writes:
"James Dunne" <james.jdunne gmail.com> wrote in message 
news:dvpa6h$ltk$1 digitaldaemon.com...
 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
Thanks! That helps a lot for me as well. So then am I still correct in that D should work with a wchar* ? BTW, do you have an MSDN reference for that info? -- -----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
VB strings are equivalent to COM's BSTR (which is wchar*), so you should be using SysAllocString and SysFreeString on the D side, just as you would with COM in C/C++. This article has some good pointers for interfacing VB with C++, which might help. http://www.flipcode.com/articles/article_vbdlls.shtml
Mar 21 2006
prev sibling next sibling parent reply Rory Starkweather <Rory_member pathlink.com> writes:
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
Mar 21 2006
parent reply Rory Starkweather <Rory_member pathlink.com> writes:
How do I join this newsgroupd if that is what this is? What do I use for NNTP?
Mar 21 2006
parent reply Lars Ivar Igesund <larsivar igesund.net> writes:
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.
Mar 21 2006
parent Rory Starkweather <Rory_member pathlink.com> writes:
Thanks. It was as easy as you said. 
Mar 21 2006
prev sibling parent reply James Dunne <james.jdunne gmail.com> writes:
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
Mar 21 2006
parent xs0 <xs0 xs0.com> writes:
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
Mar 21 2006
prev sibling parent reply Rory Starkweather <Rory_member pathlink.com> writes:
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 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); } 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); 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.
Mar 21 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
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
Mar 21 2006
next sibling parent Rory Starkweather <starkweatherr mchsi.com> writes:
 
 
 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.
Mar 21 2006
prev sibling parent reply Rory Starkweather <starkweatherr mchsi.com> writes:
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); }
Mar 21 2006
next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
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
Mar 21 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
James Dunne wrote:
 Rory Starkweather wrote:
 
 ...
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.
The working code is attached with a sample Excel spreadsheet with embedded VBA test code. Since VB uses equivalents of D's wchar* strings, you cannot easily use D's phobos string handling functions, since most of them expect char[] arguments, not wchar[]. My conclusion is that we really need wchar[] and dchar[] string-handling functions in phobos, or at least be assured that all the string-handling functions which accept char[] arguments assume UTF-8 encoding, not just ASCII. I had to look at the std.string.d module's find() method to see if it is accepting ASCII or UTF-8, and I couldn't figure out which! The code is: int find(char[] s, dchar c) { char* p; if (c <= 0x7F) { // Plain old ASCII p = cast(char*)memchr(s, c, s.length); if (p) return p - cast(char *)s; else return -1; } // c is a universal character foreach (int i, dchar c2; s) { if (c == c2) return i; } return -1; } This doesn't make a lick of sense to me why one can iterate over a char[] with foreach, expecting dchars to come out of it outside the range of ASCII... is there something going on under the hood that I'm not aware of? Is this code trying to imply that the char[] is being treated as UTF-8 magically? -- -----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
Mar 22 2006
parent reply "Derek Parnell" <derek psych.ward> writes:
On Thu, 23 Mar 2006 02:59:09 +1100, James Dunne <james.jdunne gmail.com>  
wrote:



 I had to look at the std.string.d module's find() method to see if it is
 accepting ASCII or UTF-8, and I couldn't figure out which!  The code is:

 int find(char[] s, dchar c)
 {
      char* p;

      if (c <= 0x7F)
      {	// Plain old ASCII
 	p = cast(char*)memchr(s, c, s.length);
 	if (p)
 	    return p - cast(char *)s;
 	else
 	    return -1;
      }

      // c is a universal character
      foreach (int i, dchar c2; s)
      {
 	if (c == c2)
 	    return i;
      }
      return -1;
 }

 This doesn't make a lick of sense to me why one can iterate over a
 char[] with foreach, expecting dchars to come out of it outside the
 range of ASCII...  is there something going on under the hood that I'm
 not aware of?
The foreach() has a mode of operation that automatically converts UTF encodings one character at a time. Thus foreach(dchar c; "abcdef"c) is valid code.
 Is this code trying to imply that the char[] is being
 treated as UTF-8 magically?
char[] *is* utf-8 it is not ASCII. No magic here. -- Derek Parnell Melbourne, Australia
Mar 23 2006
parent reply James Dunne <james.jdunne gmail.com> writes:
Derek Parnell wrote:
 On Thu, 23 Mar 2006 02:59:09 +1100, James Dunne 
 <james.jdunne gmail.com>  wrote:
 
 
 
 I had to look at the std.string.d module's find() method to see if it is
 accepting ASCII or UTF-8, and I couldn't figure out which!  The code is:

 int find(char[] s, dchar c)
 {
      char* p;

      if (c <= 0x7F)
      {    // Plain old ASCII
     p = cast(char*)memchr(s, c, s.length);
     if (p)
         return p - cast(char *)s;
     else
         return -1;
      }

      // c is a universal character
      foreach (int i, dchar c2; s)
      {
     if (c == c2)
         return i;
      }
      return -1;
 }

 This doesn't make a lick of sense to me why one can iterate over a
 char[] with foreach, expecting dchars to come out of it outside the
 range of ASCII...  is there something going on under the hood that I'm
 not aware of?
The foreach() has a mode of operation that automatically converts UTF encodings one character at a time. Thus foreach(dchar c; "abcdef"c) is valid code.
Okay, that's where I was confused. Thanks!
 Is this code trying to imply that the char[] is being
 treated as UTF-8 magically?
char[] *is* utf-8 it is not ASCII. No magic here.
I understand that, I just didn't know the hidden foreach magic. -- -----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
Mar 23 2006
parent reply Rory Starkweather <starkweatherr mchsi.com> writes:
  I guess I would like to ask why I shouldn't do this at the same time I 
ask how to do it.

  I've been looking at a piece of code like:

	foreach (int i, dchar c; theString)
	{
                 if (c == searchChar)
		return i + 1;
	}
	return 0;
}

  I understand the reason for doing this, but prefer to do things like this:

	int iPointer;
	
	iPointer = 0;
	foreach (int i, dchar c; theString)
	{
                 if (c == searchChar)
		iPointer =  i + 1;
		// ?? break;
	}
	return (iPointer);
}

  I realize that the extra integer takes up a little memory space, but . . .

  My questions are:
Will 'break' work here?
Why not do it this way?
Mar 23 2006
parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 23 Mar 2006 17:51:09 -0600, Rory Starkweather wrote:

   I guess I would like to ask why I shouldn't do this at the same time I 
 ask how to do it.
 
   I've been looking at a piece of code like:
 
 	foreach (int i, dchar c; theString)
 	{
                  if (c == searchChar)
 		return i + 1;
 	}
 	return 0;
 }
 
   I understand the reason for doing this, but prefer to do things like this:
 
 	int iPointer;
 	
 	iPointer = 0;
 	foreach (int i, dchar c; theString)
 	{
                  if (c == searchChar)
 		iPointer =  i + 1;
 		// ?? break;
 	}
 	return (iPointer);
 }
 
   I realize that the extra integer takes up a little memory space, but . . .
 
   My questions are:
 Will 'break' work here?
Yes it will, though it should be coded ... iPointer = 0; foreach (int i, dchar c; theString) { if (c == searchChar) { iPointer = i + 1; break; } } return (iPointer);
 Why not do it this way?
It is just a coding-style issue. People code to different standards. BTW, using the foreach this way can be misleading. The pointer value returned represents the number of dchars examined and *not* an index into theString. This is significant if theString is not a dchar[]. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 24/03/2006 11:07:48 AM
Mar 23 2006
next sibling parent reply Oskar Linde <olREM OVEnada.kth.se> writes:
Derek Parnell wrote:

 BTW, using the foreach this way can be misleading. The pointer value
 returned represents the number of dchars examined and *not* an index into
 theString. This is significant if theString is not a dchar[].
That is not correct. The index returned is an index into the char[] array, not the number of dchars processed: void main() { foreach(uint ix, dchar c; "åäö"c) writefln("c = %s, ix = %s",c,ix); } Prints: c = å, ix = 0 c = ä, ix = 2 c = ö, ix = 4 /Oskar
Mar 24 2006
next sibling parent reply Rory Starkweather <starkweatherr mchsi.com> writes:
Oskar Linde wrote:
 Derek Parnell wrote:
=20
=20
BTW, using the foreach this way can be misleading. The pointer value
returned represents the number of dchars examined and *not* an index in=
to
theString. This is significant if theString is not a dchar[].
=20 =20 That is not correct. The index returned is an index into the char[] arr=
ay,
 not the number of dchars processed:
=20
 void main() {
         foreach(uint ix, dchar c; "=E5=E4=F6"c)
                 writefln("c =3D %s, ix =3D %s",c,ix);
 }
=20
 Prints:
=20
 c =3D =E5, ix =3D 0
 c =3D =E4, ix =3D 2
 c =3D =F6, ix =3D 4
=20
 /Oskar
I'm having some trouble understanding this implementation of the=20 'foreach' construct. From the definiton of the'foreach' expression, the=20 purpose of the 'c' in . . .; "=E5=E4=F6"c) is not clear to me. Does this = implicitly declare an array of items with the same data type as 'c'? In=20 other words, three dchars in this case? From Oskar's comment that seems=20 unlikely. For me a large part of the problem is the variable naming convention=20 in the documentation, which seems a little ambiguous, although reading=20 the entries carefully usually clarifies things. I think I am just not=20 used to one letter variable names yet. A style I have never been=20 comfortable with. Oddly enough, I am also trying to learn Oberon-2 now,=20 and Wirth uses the same convention.
Mar 24 2006
parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Rory Starkweather wrote:
 Oskar Linde wrote:
 Derek Parnell wrote:


 BTW, using the foreach this way can be misleading. The pointer value
 returned represents the number of dchars examined and *not* an index 
 into
 theString. This is significant if theString is not a dchar[].
That is not correct. The index returned is an index into the char[] array, not the number of dchars processed: void main() { foreach(uint ix, dchar c; "åäö"c) writefln("c = %s, ix = %s",c,ix); } Prints: c = å, ix = 0 c = ä, ix = 2 c = ö, ix = 4 /Oskar
I'm having some trouble understanding this implementation of the 'foreach' construct. From the definiton of the'foreach' expression, the purpose of the 'c' in . . .; "åäö"c) is not clear to me. Does this implicitly declare an array of items with the same data type as 'c'? In other words, three dchars in this case? From Oskar's comment that seems unlikely.
No, the c is a suffix to the string literal, defining it as a char[]. Other suffixes are w and d for wchar[] and dchar[] respectively. Here follows a clearer version (with longer variable names ;) ): void main() { char[] string = "åäö"; // contains 6 UTF-8 code units foreach(uint index, dchar character; string) writefln("character = %s, index = %s",character,index); } In this case, the c suffix is superfluous since the data type of string (char[]) makes the conversion implicit. /Oskar
Mar 24 2006
parent Rory Starkweather <starkweatherr mchsi.com> writes:
follows a clearer version (with longer variable names ;) ):
=20
 void main() {
     char[] string =3D "=E5=E4=F6"; // contains 6 UTF-8 code units
         foreach(uint index, dchar character; string)
                 writefln("character =3D %s, index =3D %s",character,ind=
ex);
 }
=20
 In this case, the c suffix is superfluous since the data type of string=
=20
 (char[])  makes the conversion implicit.
=20
 /Oskar
So this is like using & after a number in VB to say that it is type=20 Long? I thought that kind of thing was only used in languages that=20 didn't require variable type declarations. I can see how it would come=20 in handy though. Thanks.
Mar 24 2006
prev sibling parent "Derek Parnell" <derek psych.ward> writes:
On Fri, 24 Mar 2006 19:05:30 +1100, Oskar Linde <olREM OVEnada.kth.se>  
wrote:

 Derek Parnell wrote:

 BTW, using the foreach this way can be misleading. The pointer value
 returned represents the number of dchars examined and *not* an index  
 into
 theString. This is significant if theString is not a dchar[].
That is not correct. The index returned is an index into the char[] array, not the number of dchars processed: void main() { foreach(uint ix, dchar c; "åäö"c) writefln("c = %s, ix = %s",c,ix); } Prints: c = å, ix = 0 c = ä, ix = 2 c = ö, ix = 4 /Oskar
Thanks. It didn't used to be this way, I believe. -- Derek Parnell Melbourne, Australia
Mar 24 2006
prev sibling parent Rory Starkweather <starkweatherr mchsi.com> writes:
Derek Parnell wrote:
 On Thu, 23 Mar 2006 17:51:09 -0600, Rory Starkweather wrote:
 
 
  I guess I would like to ask why I shouldn't do this at the same time I 
ask how to do it.

  I've been looking at a piece of code like:

	foreach (int i, dchar c; theString)
	{
                 if (c == searchChar)
		return i + 1;
	}
	return 0;
}

  I understand the reason for doing this, but prefer to do things like this:

	int iPointer;
	
	iPointer = 0;
	foreach (int i, dchar c; theString)
	{
                 if (c == searchChar)
		iPointer =  i + 1;
		// ?? break;
	}
	return (iPointer);
}

  I realize that the extra integer takes up a little memory space, but . . .

  My questions are:
Will 'break' work here?
Yes it will, though it should be coded ...
Understood. The // ?? was added for emphasis.
 
  iPointer = 0;
  foreach (int i, dchar c; theString)
  {
    if (c == searchChar)
    {
      iPointer =  i + 1;
      break;
    }
  }
  return (iPointer);
 
 
 
Why not do it this way?
It is just a coding-style issue. People code to different standards. BTW, using the foreach this way can be misleading. The pointer value returned represents the number of dchars examined and *not* an index into theString. This is significant if theString is not a dchar[].
Good point. Thanks for mentioning it.I hadn't really considered that. Another option that has been suggested is using 'ifind' after suitable conversions. 'ifind' is pretty much guaranteed to give me a pointer to the actual character I want, isn't it?
Mar 24 2006
prev sibling parent reply David L. Davis <SpottedTiger yahoo.com> writes:
Rory, I've put together some code that I got to work, you can download it in the
following zip file: http://spottedtiger.tripod.com/Downloads/SampleDLL.zip

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
Mar 21 2006
parent tjohnson at prtsoftware . com <tjohnson_member pathlink.com> writes:
In article <dvqi0d$29mi$1 digitaldaemon.com>, David L. Davis says...
Rory, I've put together some code that I got to work, you can download it in the
following zip file: http://spottedtiger.tripod.com/Downloads/SampleDLL.zip

David L.

-------------------------------------------------------------------
"Dare to reach for the Stars...Dare to Dream, Build, and Achieve!"
-------------------------------------------------------------------

MKoD: http://spottedtiger.tripod.com/D_Language/D_Main_XP.html
Thanks. I was going to ask for this. Tom J
Mar 22 2006