Win32下安装PyLucene

搜索良久,试验多次,终于成功,发现其实并不麻烦,只是网上把事情说清楚的参考太少了。如下是我安装PyLucene的过程与文件详情,无探讨,仅记录:
1. 下载PyLucene与Jcc
从如下地址下载PyLucene和Jcc的egg:
https://code.google.com/a/apache-extras.org/p/pylucene-extra/downloads/list
我用的是Pythong 2.75,下载了下面两个egg
lucene-3.6.2-py2.7-win32.egg
JCC-2.15-py2.7-win32.egg
2. 下载安装jdk
我下载安装的jdk是:
jdk-6u45-windows-i586.exe
安装时使用的是默认安装位置
3. 安装PyLucene
easy_install.exe在目录“C:\python27\scripts\”,方便起见,我在安装时把 *.egg文件拷贝到这个目录里了,在UltraEdit的“DOS命令”中操作:
工作目录:
C:\python27\scripts\
命令行:
easy_install lucene-3.6.2-py2.7-win32.egg
easy_install JCC-2.15-py2.7-win32.egg
4. 将jvm.dll所在目录添加到Path环境变量(不清楚这一步是否真有必要):
C:\Program Files\Java\jdk1.6.0_45\jre\bin\client
安装完成!

VBA (calling|using|调用) Python (code|script|代码、脚本) with socket

如果只想调脚本,执行一个动作,用命令行管道就行。如果需要打开一个Python进程,在其Global或者自定义的命名空间里为VBA之类的应用实现一个类似“宏语言”的工具环境,该怎么办?其实不难,网上关于这个问题的探讨很多,用COM、MS ScriptControl可以达到同样的目的,这方面资料很多,不多说了。关于做一个像Python Shell那样的东西,提供一段参考代码:

import sys
wsp={}
def interpretString(exp):
    try:
        result_object = eval(exp, wsp)
        if result_object == None:
            return '' + '\n'
        else:
            return str(result_object)+'\n'
    except:
        try:
            exec exp in wsp
            return '>>' + str(exp)+'\n'
        except:
            return str(sys.exc_info()[1])+'\n'

(参考Python Programming for Win32)

上述代码是一个解释单行Python代码的简单解释器,在WSP命名空间里工作,能eval的就返回值,不能的就exec,有错的返回错误注解,WSP可以清空,比如用ScriptControl,可以这样操作:ExecuteStatement (“exec ‘wsp.clear()’ in globals()”)

说说用Socket来实现同样的功能。

使用socket将VBA等Windows应用和Python结合起来,Python方面无须安装 Python for Windows Extensions (Pywin32),实际上,Pywin32时不时会出现莫名其妙的故障。

“In Python, the interpreter is always available” (Python Programming for Win32),只要解决了Python和应用程序间的通讯问题,对于脚本、函数代码片段、交互式解释而言都不成问题。COM就是一种通讯机制,而Socket也能简单、直白、稳定地实现同样的功能。很简单的思路:用Python做提供函数或解释代码的服务器,这也许就是所谓RPC。

以下是Python手册里提供的SocketServer示例代码,很简单:

import SocketServer
class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.data = self.request.recv(1024).strip()
        print "{} wrote:".format(self.client_address[0])
        print self.data
        self.request.sendall(self.data.upper())

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()

这是一段让人欣喜的代码,超级简单,却很有启发的力量:向这个服务器添加函数,客户端就可以通过Socket通讯“调用”这些函数,实际上是Python执行被请求的代码,返回结果。将上文第一段代码添加到这个服务器,在客户端制作一个PythonShell一样的工具十分容易。

Socket通讯的解决
VB.net里可以用TCPClient
VB6里用Socket控件
VBA里怎么办?
办法其实也不少:
1. 用Socket控件,要装VB6(Runtime),VB6是我最喜欢的编程工具,但是不幸“过时”了。
2. 调API,网上能找到一些代码,懒得钻研这种方法。
3. 用C/C++等制作客户端和“连结件”(connector)DLL,VBA调用Connector,这个办法不错,我用PowerBasic做了一个,代码如下,就是PowerBasic手册里的例子:

'VBA声明:Private Declare Function TCPSCK Lib "TCPSCK.DLL" (ByVal CommandLine As String, ByVal portN As Integer, ByVal Waiting As Long) As String

#COMPILE DLL
#DIM ALL

FUNCTION TCPSCK (BYVAL CommandLine AS STRING, BYVAL portN AS INTEGER, BYVAL Waiting AS LONG) EXPORT AS STRING

    LOCAL nSocket AS LONG
    LOCAL sBuffer AS STRING
    LOCAL sPacket AS STRING

    TCP OPEN PORT portN AT "localhost" AS nSocket TIMEOUT Waiting
    IF ERR THEN
        FUNCTION = "Error opening port: " + STR$(ERR)
        EXIT FUNCTION
    END IF

    TCP PRINT nSocket, CommandLine;

    ERRCLEAR

    DO
        TCP RECV nSocket, 1024, sBuffer
        sPacket = sPacket + sBuffer
    LOOP UNTIL sBuffer = "" OR ISTRUE EOF(nSocket) OR ISTRUE ERR

    IF ERR THEN
        TCP CLOSE nSocket
        sPacket = "Error" + STR$(ERR)
    ELSE
        TCP CLOSE nSocket
    END IF

    FUNCTION = sPacket

END FUNCTION

4. 用WinHttpRequest或者XMLHttpRequest,稍微复杂一点,因为这些都是Http Request,接发消息都涉及报头,Python方面必须作一些HTTP报头处理:

客户端发消息(VBA,使用WinHttpRequest):

Dim rq As New WinHttpRequest
rq.Open "GET", "http://localhost:9999/", False
'因为用的是SocketServer,无所谓GET还是POST
rq.Send "#code:" & vbCrLf & "2*3"
'把Python代码放在"#code:\r\n"后面
Debug.Print StrConv(rq.ResponseBody, vbUnicode)

Python服务器端:

def handle(self):
        r=re.compile(r'#code:\r\n(.*)') #用正则表达式提取"#code:\r\n"后面的代码
        m = r.search(self.request.recv(1024).strip())
        if m:
            self.code=m.group(1) #用正则表达式提取"#code:\r\n"后面的代码
            if self.code:
                print "{} wrote:".format(self.client_address[0])
                print self.code
                rslt =self.interpretString(str(self.code))
                print rslt
                self.request.send("%s %d %s \r\n" % ('HTTP/1.0', 200, '')+'\r\n'+str(rslt))
                #发送基本报头和解释结果,否则客户端的Http Request对象会报错"unrecognizable message"
        else:
            self.request.send("%s %d %s \r\n" % ('HTTP/1.0', 200, ''))

Windows安装Python+NLTK+Windows Script Component

之前装的是内含Win32 extensions的ActivePython (2.7),不料在试验WSC时发现一注册就报错,重装ActivePython无效,就从python.org下了一个Python 2.7装上了,不含Win32 Extensions,需要安装 (http://sourceforge.net/projects/pywin32/)。

随便找个现成的WSC,点右键注册一下试试,注册成功就说明WSC运行需要的条件都没有问题了。

安装NLTK(nltk.org)

网页上有这么一段:

These instructions assume that you do not already have Python installed on your machine. If you do, you can skip to the final step and just install NLTK.
这部分说明不够严谨,安装Python后,“32/64-bit binary installation” 项下的Numpy和PyYAML都是必要的,并非optional。
NLTK安装好之后,打开Python Shell (IDLE或者Command Line),在提示符后输入import nltk,等下一行提示符出现,然后键入nltk.download(),跳出安装NLTK data的安装界面,按需选择下载。
安装告成。
之后写WSC,按样板做,可简可繁。<?component error=”true” debug=”true”?>这行在调试时应保留,确定没问题后把它删掉。Registration中GUID行可以删掉,系统自动处理/分配。在PythonWin或者Komodo等编辑器里调试好代码,拷贝到WSC的CDATA部分,WSC完成。
在WSC右键菜单点注册,成功消息出现,全部工作完成。。。
还有一点不确定,很可能是必要的,需要运行下面这个脚本,在系统里注册Python script:
..\Python27\Lib\site-packages\win32comext\axscript\client\pyscript.py

A Hypothetical Collocation Association Measurement with Rank Ordering

This is only a hypothetical method. Dunning proposed LLR as a non-parametric method.  Many non-parametric tests use the rank order of the data. I thought it might be a good idea to design an AM on the basis of rank ordering.  I tried something and it kind of worked, but I am not good at math. So I call this AM a hypothetical method.
If this method is theoretically and mathematically legitimate, I think it can be useful in certain cases…
I call this AM RankDiff. In the model of one node word and some collocates, say FC is the frequency of a collocate and FNC the node-collocate cooccurrences; FCS is the set of all FC data, and FNCS the set of all FNC data.  I don’t know how to write good math formula, but in the format of Excel formula it is:
RankDiff = (Rank(FC, FCS)-Rank(FNC, FNCS)) / (Rank(FC, FCS)+Rank(FNC, FNCS))
The “Rank” function is actually the following RankTied function, in descending order (ignoring argument “order” or passing a zero to it)  …
Function RANKTIED(number As Double, Ref As Range, Optional order)
On Error GoTo ErrorVal
Dim r1 As Double
If IsMissing(order) Then order = 0
r1 = ((Application.Count(Ref) + 1) – (Application.Rank(number, Ref) + Application.Rank(number, Ref, 1))) / 2
RANKTIED = Application.Rank(number, Ref, order) + r1
GoTo FuncEnd
ErrorVal:
RANKTIED = [#VALUE]
FuncEnd:
End Function

PowerBasic:Capture Command Line StdErr and StdOut

I want to capture command line StdErr and StdOut separately (with two pipes). I tried a little threading and it works fine.
#COMPILE EXE
#DIM ALL
#INCLUDE "Win32API.inc"

%STARTF_USESTDHANDLES = 256
%STARTF_USESHOWWINDOW = 1
GLOBAL sErr AS STRING
GLOBAL sOutput AS STRING
FUNCTION PBMAIN () AS LONG
    DIM CmdLine AS STRING
    DIM proc AS PROCESS_INFORMATION
    DIM ret AS LONG, hp AS LONG
    DIM start AS STARTUPINFO
    DIM sa AS SECURITY_ATTRIBUTES
    DIM hReadPipe AS LONG
    DIM hWritePipe AS LONG
    DIM hReadPipe2 AS LONG
    DIM hWritePipe2 AS LONG
    DIM lngBytesRead AS LONG
    DIM sBuffer AS STRING * 1024
    DIM hThread AS DWORD
    DIM s AS LONG

    CmdLine="perl C:\Perl\bin\KWIC.PL market C:\Perl\bin\becorpus.txt"

    sa.nLength = LEN(sa)
    sa.bInheritHandle = 1

    ret = CreatePipe(hReadPipe, hWritePipe, sa, BYVAL 0&)
    IF ret = 0 THEN
    sErr="[#failure]"
    EXIT FUNCTION
    END IF

    ret =CreatePipe(hReadPipe2,hWritePipe2, sa,BYVAL 0&)
    IF ret = 0 THEN
    CloseHandle hWritePipe
    CloseHandle hReadPipe
    sErr="[#failure]"
    EXIT FUNCTION
    END IF

    start.cb = LEN(start)
    start.dwFlags = 256  OR 1

    start.hStdOutput = hWritePipe
    start.hStdError = hWritePipe2
    start.wShowWindow = 1 'SW_HIDE

    ret = CreateProcess("", _
                 BYVAL STRPTR(CmdLine), _
                 sa, _
                 sa, _
                 1, _
                 %NORMAL_PRIORITY_CLASS, _
                 BYVAL %NULL, _
                 BYVAL %NULL, _
                 Start, _
                 Proc)
     IF ret =0 THEN
         CloseHandle hWritePipe
         CloseHandle hReadPipe
         CloseHandle hWritePipe2
         CloseHandle hReadPipe2
         sErr="[#failure]"
         EXIT FUNCTION
     END IF

  CloseHandle proc.hThread
  CloseHandle hWritePipe2
  CloseHandle hWritePipe

  THREAD CREATE readStdErr(hReadPipe2) TO hThread

  CloseHandle proc.hProcess
       DO
            Ret = ReadFile(hReadPipe, sBuffer, 1024, lngBytesRead, BYVAL 0&)
            sOutput = sOutput & LEFT$(sBuffer, lngBytesRead)
       LOOP WHILE Ret <> 0
       CloseHandle hReadPipe
       #DEBUG PRINT sErr
       #DEBUG PRINT soutput

END FUNCTION

THREAD FUNCTION readStdErr(BYVAL readpipe AS LONG)AS LONG
   DIM ret AS LONG
   DIM lngBytesRead AS LONG
   DIM sBuffer AS STRING * 1024
   DO
   Ret = ReadFile(readpipe, sBuffer, 1024, lngBytesRead, BYVAL 0&)
   sErr = sErr & LEFT$(sBuffer, lngBytesRead)
   LOOP WHILE Ret <> 0
   CloseHandle readpipe
END FUNCTION

Windows Script Component Solution: NLTK POS Tagger

This code is alright, but with or without the "error & debug" thing an error message always pops up on the first run.
WSC code:

<?xml version="1.0"?>
<component>
<?component error="true" debug="true"?>
<registration
	description="POSTag"
	progid="PosTag.WSC"
	version="1.00"
>
</registration>
<public>
	<method name="TagIt">
		<PARAMETER name="text"/>
	</method>
</public>
<script language="Python">
<![CDATA[
import nltk
from nltk.tokenize import word_tokenize, sent_tokenize
def TagIt(text):
	s=""
	for sentence in sent_tokenize(text):
		tagged = nltk.pos_tag(nltk.word_tokenize(sentence))
		for t in tagged:
			s+= t[0]+'_'+t[1]+' '
	return s;
]]>
</script>
</component>

-----------
VBA code:
-----------
Private Sub Command1_Click()
Dim o As Object
Set o = CreateObject("PosTag.WSC")
Debug.Print o.TagIt("Competition for this kind of goods is tough. We cant persuade the end-users to buy your products at this price.")
End Sub

MS Word + Hunpos POS Tagger

Private Sub CommandButton1_Click()
Dim r As Long
Dim fso As New FileSystemObject
Dim ts As TextStream
Set ts = fso.CreateTextFile(“c:\pat.txt”, True, False)
Dim w As Range ‘[1_1]
For Each w In ThisDocument.Words ‘[1_2]
If Not Trim(w.text) = “” Then ts.Write Trim(w.text) & vbLf ‘[1_3]
Next
ts.Close
TextBox.text = ExecCmdCaptureOutput(“cmd /c type c:\pat.txt|C:\apps\hunpos\hunpos-tag.exe C:\apps\hunpos\english.model”, r) ‘[2]
End Sub
[1_1] -[1-3] demonstrates how to use Word internal object to realize a simple tokenizer. Notice the “vblf” at the end of line [1-3],Hunpos requires pre -tokenized data,one word each line. The line break is Lf of Unix, not CrLf of Windows.
[2] Function “ExecCmdCaptureOutput”(from Shell.bas)  starts a new process and capture its output. Commandline syntax of Hunpos is rather simple. In windows, if Hunpos is used in commandline console, start with “type” command to open a text file, and pipe (|) it into Hunpos tagger. “English.model” is the trained English data Hunpos tagger uses.

Friedman Test VBA Code [not adjusted for tied values]

‘RG is  the data table, where each column is a treatment group.  This is a multi-cell array formula. Select three cells and ‘insert the function, after RG is pecified, use “shift + ctrl” and  enter.
Function FRIEDMANTEST_ARR3(RG As Range) As Variant
Dim RCNT, CCNT, CV, SUM_RTS, DF, TALL, SSBG, SUMTG2, CHI2
Dim RR As Range
Dim CEL As Range
Dim RSLT(3)
RCNT = RG.Rows.Count
CCNT = RG.Columns.Count
DF = CCNT – 1
Dim ARR()
ReDim ARR(1 To CCNT)
Dim i
i = 0
For Each RR In RG.Cells.Rows
i = 0
For Each CEL In RR.Cells
i = i + 1
With WorksheetFunction
ARR(i) = ARR(i) + (.Count(RR) + 1 + .Rank(CEL.Value, RR, 1) – .Rank(CEL.Value, RR, 0)) / 2
End With
Next
Next
For i = 1 To CCNT
TALL = TALL + ARR(i)
SUMTG2 = SUMTG2 + ARR(i) ^ 2
Next
SSBG = SUMTG2 / RCNT – (TALL ^ 2) / (RCNT * CCNT)
CHI2 = SSBG / ((CCNT * (CCNT + 1)) / 12)
‘CHI2 = (12 / (RCNT * CCNT * (CCNT + 1))) * SUMTG2 – 3 * RCNT * (CCNT + 1)
‘FRIEDMANTEST = WorksheetFunction.ChiDist(CHI2, DF)
RSLT(1) = DF
RSLT(2) = CHI2
RSLT(3) = WorksheetFunction.ChiDist(CHI2, DF)
FRIEDMANTEST_ARR3 = RSLT
End Function

开发Global Mapper数据源插件的示例源码

Global Mapper V12之后就可以添加数据源,但是这个功能比较有限:[WMS我自己还没有搞明白,所以不谈这方面,只说关于图块服务的事情]
其一:
图块服务器(谷歌、OpenStreetMap等)
一般都使用多个服务器来平衡访问量,比如谷歌:http://khm[0123].XXXX…;再如OpenCycleMap:http://[abc].XXXX….,假设是在使用普通浏览器查看地图,如果是在图块服务器访问量比较大的时候,地图服务器会有协调,也就是说发回浏览器的图块资源URL(以谷歌为例)可能是http://khm0.XXXX… ,也可能是http://khm1.XXXX… 等。在GM中添加数据源,只能提供以上述之中单一的URL,而下载数据的时候,也就只能反复给一个图块服务器发请求,至于会不会有暂封IP之类的后果,说不清,反正有缺陷。
其二:
GM请求数据时,直接发图块编号(下面有说明和例子),所以如果图块服务器要求的URL中图块编号是经过编码的,比如常见的四叉树编码(quadkey),这种类型的图块资源地址,就不能在GM中添加了。任何在图块编号基础上有特殊URL处理的图块服务,都不能在GM里添加,最新版V14也是如此。
针对GM添加数据源的各种不足,如下方案可以解决:
该方案的原理很简单,编程制作一个简单的TCP Server,接收GM的请求,翻译后转发出去,获得数据后再发回GM。
GM请求很简单,例如:
GET /12/3290/1579.png HTTP/1.1
User-Agent: app_name
Host: XXXXXX
Connection: Keep-Alive
Cache-Control: no-cache
几个要点:
1)“/12/3290/1579” 这部分就是图块编号,具体格式是/Zoom/X/Y。提取这部分后,就可以按需要自由构造更复杂的URL,比如计算经纬度、算四叉树编码(quadkey)。
2)图块服务使用多个服务器来平衡访问量,在构造URL时,可以对此进行模拟。
3)此外,对图块服务器的请求有必要加上报头,可以用Fiddler或是HTTPWatch之类的工具观察通过浏览器使用地图时的请求报头。
4)GM发请求是同步模式,若请求失败会重发,成功收到数据或是重发失败5次,才会发出下一个新请求。
5)服务器下载到图块后,可用字节流的方式把图块数据发给GM。
6)GM图块请求的顺序是依次Y+1,填满区域宽度后X+1,就像打字,打满一行后换行。
这个方案的优点:操作简单,相当于GM的一个插件,在GM中以该服务器地址作为数据源,打开服务器,GM端的操作和使用其他数据源没有任何区别;凡是可分析或破解的图块服务URL,都可以通过这个方案导入GM。
“缺陷”:由于GM发请求是同步模式,若请求失败会重发,成功收到数据或是重发失败5次,才会发出下一个新请求,这个发请求的模式决定了GM不胜任大批量数据下载,或是所谓“抓大图”。不过,现在算是弄明白了,这并非真就是一个缺陷,在技术上,实现高效抓大图不是特别难的技术,人家不实现这种功能自有人家的道理。
除了OpenStreetMap系列、一些古旧的卫片资源之外,谷歌等图块服务器,其实原则上不支持大批量下载图块。毕竟,获取保质保量地图数据的官方途径是从数据供应商那里购买。所以,各种抓大图工具,多少都具有“旁门左道”的性质,本方案也不例外,此外,通过图块服务器URL下载数据的方法,难免有时效性,没准哪天就不能用了。
Option Explicit
Private WithEvents SOCKET As Winsock
Private WithEvents WRQ As WinHttpRequest
Private I As Integer ’这个和数组OP是用来在几个服务器间滚动的
Private CQ As String
Private OP(2) As String
Dim z, y, x As Long
Const Serverport = 8080
Dim STT, STP, DLB As Double ’这些变量是用来显示下载速度的
Private Sub SOCKET_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
If SOCKET.State <> 0 Then SOCKET.Close
SOCKET.Bind Serverport
SOCKET.Listen
End Sub
Private Sub UserForm_Initialize()
OP(0) = “a”: OP(1) = “b”: OP(2) = “c”
I = -1
Set SOCKET = New MSWinsockLib.Winsock
SOCKET.Bind Serverport
SOCKET.Listen
End Sub
Private Sub SOCKET_ConnectionRequest(ByVal requestID As Long)
SOCKET.Close
SOCKET.Accept requestID
End Sub
Private Sub SOCKET_DataArrival(ByVal bytesTotal As Long)
Dim GMREQ As String ‘GM的请求
SOCKET.GetData GMREQ
Dim MS As MatchCollection
Dim RXP As New RegExp
RXP.Pattern = “\/(\d+)\/(\d+)\/(\d+)” ‘用Regular Expression提取GM请求中的图块编号
If RXP.Test(GMREQ) = False Then
SOCKET.Close
Exit Sub
End If
Set MS = RXP.Execute(GMREQ)
CQ = MS(0).Value
TB.Text = TB.Text & CQ & vbTab
z = CLng(MS(0).SubMatches(0))
y = CLng(MS(0).SubMatches(1))
x = CLng(MS(0).SubMatches(2))
If I = 2 Then I = -1
I = I + 1
Dim URL As String: URL = “http://” & OP(I) & “.tile.opencyclemap.org/cycle” & CQ & “.png” ‘翻译请求
TB.Text = TB.Text & URL & vbCrLf
TB.SelStart = Len(TB.Text)
Set WRQ = New WinHttpRequest
WRQ.Open “GET”, URL, True ’把翻译好的请求发出去
On Error Resume Next
WRQ.Send
End Sub
Private Sub SOCKET_SendComplete()
SOCKET.Close ‘通过套接字把数据发回GM后要关闭套接字
SOCKET.Bind Serverport
SOCKET.Listen
End Sub
Private Sub WRQ_OnError(ByVal ErrorNumber As Long, ByVal ErrorDescription As String)
Set WRQ = Nothing
SOCKET.Close
SOCKET.Bind Serverport
SOCKET.Listen
End Sub
Private Sub WRQ_OnResponseStart(ByVal Status As Long, ByVal ContentType As String)
Label1.Caption = “”
If Status = 200 Then
STT = Timer
DLB = 0
Progress.Value = 0
Progress.Max = CLng(WRQ.GetResponseHeader(“Content-Length”))
Else
WRQ.Abort
Set WRQ = Nothing
SOCKET.Close
SOCKET.Bind Serverport
SOCKET.Listen
End If
End Sub
Private Sub WRQ_OnResponseDataAvailable(Data() As Byte)
DLB = DLB + UBound(Data) – 1
Progress.Value = Progress.Value + UBound(Data) – 1
On Error Resume Next
Label1.Caption = FormatNumber((DLB / 1024) / (Timer – STT), 1) & ” KB/SEC.”
End Sub
Private Sub WRQ_OnResponseFinished()
On Error Resume Next
SOCKET.SendData WRQ.ResponseBody
Progress.Value = 0
Label1.Caption = “”
End Sub
‘引用Winhttp.WinHttpRequest; VBScript RegularExpression 5.5; mswsk.ocx
‘如果用VB.net,可以用TCPListener做TCP服务器

Embed a Little Perl in VBA

We can do a little Perl in VBA with PerlEZ.dll (with ActivePerl installed). 

 

‘Declarations in a .bas module.

‘I can’t get PerlEzCall and other functions working.

Public Declare Function PerlEzCreate Lib "PerlEz.dll" _

(ByVal lpFileName As String, ByVal lpOptions As String) As Long

Public Declare Function PerlEzCreateOpt Lib "PerlEz.dll" _

(ByVal lpFileName As String, ByVal lpOptions As String, ByVal lpScriptOpts As String) As Long

Public Declare Function PerlEzDelete Lib "PerlEz.dll" (ByVal hHandle As Long) As Byte

Public Declare Function PerlEzEvalString Lib "PerlEz.dll" _

(ByVal hHandle As Long, ByVal lpString As String, ByVal lpBuffer As String, ByVal dwBufSize As Long) As Long

 

'----------------------------------------------------------------- 

‘Other code in a sub

Private Sub Command1_Click()

Dim R As Long

Dim PS As String

Dim RT As String * 1024

PS = "C:\\Perl\\bin\\KWIC.PL"

R = PerlEzCreateOpt(PS, "", "market C:\\Perl\\bin\\corpus.txt")

'Debug.Print R

R = PerlEzCreate("", "")

'R = PerlEzEvalString(R, "use Win32; Win32::MsgBox('Hello World!');", RT, Len(RT))

R = PerlEzEvalString(R, txtCode.Text, RT, Len(RT))

Debug.Print R

Debug.Print CStr(rt)

End Sub

'----------------------------------------------- 

‘Example Perl code in txtCode

‘#!/usr/bin/perl

‘sub myfunc {return "my result";}

‘myfunc();