Pass string from MS-Word macro to PureBasic DLL

Just starting out? Need help? Post your questions and find answers here.
User avatar
SimpleMind
Enthusiast
Enthusiast
Posts: 112
Joined: Sun May 18, 2003 12:40 pm
Location: Netherlands

Pass string from MS-Word macro to PureBasic DLL

Post by SimpleMind »

Hi,

I want to pass a string from MS-Word to a dll procedure.

Code: Select all

ProcedureDLL.l InitString(name.s)

MessageRequester("",name)

  ProcedureReturn 1
  
EndProcedure

In MS-Word I have a declaration and a simple procedure.

Code: Select all

Declare Function InitString Lib "IS.dll" (name As String) As Long

Public Sub inits()
    a = InitString("Whooaa")
End Sub

When I run this piece of code from MS-Word I see only gibberisch in the MessageRequester. Word uses Unicode and I have unicode enable in the compiler. But still no succes.

Does anyone know what I'm missing or doing wrong? I searched the forum but didn't find a solution to this question or a likewise problem.
Give me books, fruit, french wine, fine weather and a little music.
John Keats
KarLKoX
Enthusiast
Enthusiast
Posts: 681
Joined: Mon Oct 06, 2003 7:13 pm
Location: France
Contact:

Post by KarLKoX »

Code: Select all

ProcedureDLL.l InitString(name.p-utf8)

MessageRequester("",name)

  ProcedureReturn 1
 
EndProcedure 
:?:
"Qui baise trop bouffe un poil." P. Desproges

http://karlkox.blogspot.com/
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Doesn't vba use BSTR formatted strings?

If so, then you'll need to convert from bstr to a regular null-terminated string. There are plenty of examples scattered throughout these forums to do just that.
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

ProcedureDLL.l InitString(name.p-utf8)
Afaik this is only legal in an Import, Interface or Prototype declaration:
PB Doc wrote:The pseudotypes can only be used with prototypes, interfaces and imported functions. The pseudotypes does the appropriate conversion only if it is necessary: for example using a 'p-ascii' pseudotype in an ascii compiled program makes no difference with regular string type.
Last edited by netmaestro on Sat Mar 03, 2007 11:06 pm, edited 1 time in total.
BERESHEIT
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

This looks like a reasonable try:

Code: Select all

Procedure.s ReadBSTR(bstr) ; by Fr34k
  length = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0) 
  Text$ = Space(length) 
  WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @Text$, length, 0, 0)    
  ProcedureReturn Text$ 
EndProcedure 

ProcedureDLL.l InitString(*pbstr) 
  MessageRequester("",ReadBSTR(*pbstr) )
  ProcedureReturn 1 
EndProcedure 
No need to enable Unicode exe for this approach.
BERESHEIT
User avatar
SimpleMind
Enthusiast
Enthusiast
Posts: 112
Joined: Sun May 18, 2003 12:40 pm
Location: Netherlands

Post by SimpleMind »

Thanks people, for the code suggestions so far. Two approaches:

1. With the p-unicode pseudotype

PureBasic-code

Code: Select all

; Name: IS2.pb
; dll name: IS2.dll
; Test with p-inicode
; Compiler options: Create Unicode executeable

Prototype.l InitString2(name.p-unicode)

ProcedureDLL.l InitString2(name.s)
MessageRequester("Message from IS2.dll",name)
  ProcedureReturn 1
EndProcedure
VBA-Code in Word

Code: Select all

Declare Function InitString2 Lib "IS2.dll" (name As String) As Long

Public Sub inits1()
    a = InitString2("Name")
End Sub
Result: Same gibberish as before.


2. With the Binary string approach.

Code: Select all

; Name: IS.pb
; dll name: IS.dll
; Test with binary string approach
; Compiler options: Create Unicode executeable: off

Procedure.s ReadBSTR(bstr) ; by Fr34k 
  length = WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, 0, 0, 0, 0) 
  Text$ = Space(length) 
  WideCharToMultiByte_(#CP_ACP, 0, bstr, -1, @Text$, length, 0, 0)    
  ProcedureReturn Text$ 
EndProcedure 

ProcedureDLL.l InitString(*pbstr) 
  MessageRequester("",ReadBSTR(*pbstr) ) 
  ProcedureReturn 1 
EndProcedure 
VBA-Code in Word I use to call this suggested code.

Code: Select all

Declare Function InitString Lib "IS.dll" (name As String) As Long
 
Public Sub inits2()
    a = InitString("Name")
End Sub
Result: Gibberish

Tested the last also with:

Code: Select all

Declare Function InitString Lib "IS.dll" (name As Any) As Long

Another approach 3
The next is a (incomplete) code snippet I once adapted for named pipe communication between Word and Excel.
Here I translated the string first from Unicode into ASCII with the StrConv() function in VBA and then passed it to the Write() function.

I dimmed SendBuffer:

Code: Select all

Dim SendBuffer() As Byte
This is VBA-code:

Code: Select all

    res(0) = ConnectNamedPipe(hPipe, ByVal 0)
       
    res(1) = ReadFile(hPipe, RecieveBuffer(0), _
                             UBound(RecieveBuffer), _
                             lpNumberOfBytesRead, ByVal 0)
       
    Debug.Print Err.LastDllError

    'Get the string out of the byte array.
    For i = 0 To lpNumberOfBytesRead - 1
        temp = temp & Chr(RecieveBuffer(i))
    Next i
    
    'And put it on the textbox.
    Me.TbRecieve.Text = temp
    
    temp = UserForm2.TbSend
    SendBuffer = StrConv(temp, vbFromUnicode)
       
    'Redim the SendBuffer and fill the rest of the buffer 
    'with nullchars.
    ReDim Preserve SendBuffer(BUFFSIZE)
    nNumberOfBytesToWrite = UBound(SendBuffer)
    lpNumberOfBytesWritten = nNumberOfBytesToWrite
       
    'Write the number of bytes requested
    res(2) = WriteFile(hPipe, SendBuffer(0), UBound(SendBuffer), _
                                lpNumberOfBytesWritten, ByVal 0)
End of VBA-code.

If you look at the WriteFile API function, the SendBuffer(0) is dimmed as "lpBuffer as Any".

Code: Select all

   Declare Function ReadFile Lib "kernel32" ( _
      ByVal hFile As Long, _
      lpBuffer As Any, _
      ByVal nNumberOfBytesToRead As Long, _
      lpNumberOfBytesRead As Long, _
      lpOverlapped As Any) As Long
If I use this approach I have to pass a pointer of the ASCII array to PureBasic. How do I pick this up in PureBasic?
Give me books, fruit, french wine, fine weather and a little music.
John Keats
User avatar
SimpleMind
Enthusiast
Enthusiast
Posts: 112
Joined: Sun May 18, 2003 12:40 pm
Location: Netherlands

Post by SimpleMind »

I found some VB related information about strings and how they are build.

http://www.romanpress.com/Articles/Stri ... trings.htm

http://msdn2.microsoft.com/en-us/librar ... e.10).aspx
Give me books, fruit, french wine, fine weather and a little music.
John Keats
User avatar
SimpleMind
Enthusiast
Enthusiast
Posts: 112
Joined: Sun May 18, 2003 12:40 pm
Location: Netherlands

Post by SimpleMind »

I found a solution given by user Seldon. I posted also my solution there.

http://www.purebasic.fr/english/viewtopic.php?t=12669

To all, thanks for the support!
Give me books, fruit, french wine, fine weather and a little music.
John Keats
User avatar
SimpleMind
Enthusiast
Enthusiast
Posts: 112
Joined: Sun May 18, 2003 12:40 pm
Location: Netherlands

Post by SimpleMind »

For simple string passing it is a nice solution. I can show the text in a messagebox. But when I put the stringvariable as parameter in a function inside a dll, the string is not interpreted as a string. I do not get an error but the function doesn't work either.

Do I have to convert the string back from BSTR into a PB format?
Give me books, fruit, french wine, fine weather and a little music.
John Keats
Post Reply