问题描述:.net开发的新系统中有许多web服务,需要诸多旧的系统调用,其它的系统可能是
PB,dephi,c++,vb等开发的。由于版本比较老,所以用了Dcom机制,统一接口,使用.net(c#)写的webservice.DCOM的包装是用C++写的dll,源程序如下。dll放到老系统端,老系统客户端传出5个参数,供dll序列化,传到服务器上,根据web服务修改数据库中的记录。现在的问题是只有供dephi使用的系统不能成功调用dll,也不出什么错误,就是不能改数据。dephi程序如下。请高手指点。
C++dll源码如下,主要式test方法。
#include "stdafx.h"
#include "dll.h"#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif/////////////////////////////////////////////////////////////////////////////
// CDllAppBEGIN_MESSAGE_MAP(CDllApp, CWinApp)
//{{AFX_MSG_MAP(CDllApp)
// NOTE - the ClassWizard will add and remove mapping macros here.
//    DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_MSG_MAP
END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////
// CDllApp constructionCDllApp::CDllApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}/////////////////////////////////////////////////////////////////////////////
// The one and only CDllApp objectCDllApp theApp;
//初始化Connector函数
ISoapConnectorPtr initConnector ()
{
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader;
    ISoapConnectorPtr Connector;
// Connect to the service.
Connector.CreateInstance(__uuidof(HttpConnector30));
Connector->Property["EndPointURL"] = WSURI;
return Connector;
}extern "C" LONG __declspec(dllexport) __stdcall myfunction(VARIANT FAR* vArray)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
    SAFEARRAY FAR* psa = NULL;
BSTR *pbstr = NULL;

LPSTR strtemp; HRESULT hr;
LONG j = 0;
LONG  lLBound, lUBound;
USES_CONVERSION;
if (V_VT(vArray) != (VT_ARRAY | VT_BSTR))
         AfxThrowOleDispatchException(1001,
           "Type Mismatch in Parameter. Pass a string array by reference");
psa = V_ARRAY(vArray);

hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pbstr);
hr = SafeArrayGetLBound(psa, 1, &lLBound);
hr = SafeArrayGetUBound(psa, 1, &lUBound);
j = lUBound-lLBound+1;
LPSTR *l_array = new LPSTR[j];
_bstr_t *bstr1 = NULL;
for (int i=0;i<j;i++)
{
bstr1= new _bstr_t(pbstr[i],TRUE); 
strtemp = _com_util::ConvertBSTRToString(*bstr1);
*(l_array+i) = new char[bstr1->length()+1];

strcpy(*(l_array+i), strtemp);
bstr1 = NULL;

}
hr = SafeArrayUnaccessData(psa);
//for (int i1=0;i1<j;i1++)
//AfxMessageBox(*(l_array+i1));
//if (strcmp(*(l_array+1),"str1")==0)
//{
// delete []l_array;
//return 1;
//}
//else
//{
//return 0;
//}
CoInitialize(NULL);
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader; ISoapConnectorPtr Connector = initConnector();
Connector->Connect();
// Begin the message.
Connector->Property["SoapAction"] = "http://tempuri.org/TransWrite"; 
Connector->BeginMessage();
// Create the SoapSerializer object.
Serializer.CreateInstance(__uuidof(SoapSerializer30));
// Connect the serializer object to the input stream of the connector object.
Serializer->Init(_variant_t((IUnknown*)Connector->InputStream)); // Build the SOAP Message.
//LPSTR str[] = {str1,str2,str3,str4};
Serializer->StartEnvelope("","","");
    Serializer->StartBody("");
    Serializer->StartElement("TransWrite","http://tempuri.org/","",""); 
    Serializer->StartElement("str","http://tempuri.org/","","");
    for (int i1=0;i1<j;i1++)
AfxMessageBox(*(l_array+i1));
for (int i2=0;i2<j;i2++)
    {
   Serializer->StartElement("string","http://tempuri.org/","","");
   Serializer->WriteString(*(l_array+i2));
   Serializer->EndElement();
    }
delete []l_array;
    Serializer->EndElement();
    Serializer->EndElement();
    Serializer->EndBody();
    Serializer->EndEnvelope();
    // Send the message to the XML Web service.
    Connector->EndMessage();          // Read the response.
    Reader.CreateInstance(__uuidof(SoapReader30));    // Connect the reader to the output stream of the connector object.
    Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
   
    _bstr_t strTemp1(Reader->RpcResult->text);
    char *Result = _com_util::ConvertBSTRToString(strTemp1);
    CoUninitialize();
if(strcmp(Result,"ok.ok")==0)
return 1;
else
return 0;

 

}void initSoap()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CoInitialize(NULL);
//return "ok";
}
//就是这个方法
extern "C" LPSTR __declspec(dllexport) __stdcall test(LPSTR *lpstrArray,int leng)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CoInitialize(NULL);
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader; ISoapConnectorPtr Connector = initConnector();
Connector->Connect();
// Begin the message.
Connector->Property["SoapAction"] = "http://tempuri.org/TransWrite"; 
Connector->BeginMessage();
// Create the SoapSerializer object.
Serializer.CreateInstance(__uuidof(SoapSerializer30));
// Connect the serializer object to the input stream of the connector object.
Serializer->Init(_variant_t((IUnknown*)Connector->InputStream)); // Build the SOAP Message.
//LPSTR str[] = {str1,str2,str3,str4};
Serializer->StartEnvelope("","","");
    Serializer->StartBody("");
    Serializer->StartElement("TransWrite","http://tempuri.org/","",""); 
    Serializer->StartElement("str","http://tempuri.org/","","");
    for (int i=0;i<leng;i++)
    {
   Serializer->StartElement("string","http://tempuri.org/","","");
   Serializer->WriteString(*(lpstrArray+i));
   Serializer->EndElement();
    }
    Serializer->EndElement();
    Serializer->EndElement();
    Serializer->EndBody();
    Serializer->EndEnvelope();
    // Send the message to the XML Web service.
    Connector->EndMessage();          // Read the response.
    Reader.CreateInstance(__uuidof(SoapReader30));    // Connect the reader to the output stream of the connector object.
    Reader->Load(_variant_t((IUnknown*)Connector->OutputStream), "");
   
    _bstr_t strTemp(Reader->RpcResult->text);
    char *Result = _com_util::ConvertBSTRToString(strTemp);
    CoUninitialize();
return Result;
}LPSTR _declspec(dllexport) _stdcall endSoap()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CoUninitialize();
return "ok";
}
delphi 调用代码:
unit mainDelhpi;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, SHDocVw,Comobj,ShellAPI;
type
   TForm1 = class(TForm)
    Button1: TButton;
    GroupBox1: TGroupBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
  procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;implementation
{$R *.dfm}
function test(var a:array of pchar;b:integer):pchar; StdCall; External 'dll.dll';//静态调用dllprocedure TForm1.Button1Click(Sender: TObject);
var
 arr: array[0..4] of  pchar;
 url: string;
 rel:pchar;
begin
arr[1]:=pchar(Edit1.text);
arr[2]:=pchar(Edit2.text);
arr[3]:=pchar(Edit3.text);
arr[4]:=pchar(Edit4.text);
arr[0]:=pchar('0002');//5个参数
Edit1.SetFocus();
rel:=test(arr, 5);//调用dll方法
 url:= 'http://192.168.100.253/test/WebForm1.aspx?cliid=';//调用服务器上的网页
 url:=url+arr[0];
 
ShellExecute(handle, 'open', pchar(url), nil, nil, SW_SHOWNORMAL);end;end.

解决方案 »

  1.   

    web服务不用给出了,我试过,是正确的。
      

  2.   

    function test(CharArray:PChar;Len:integer):pchar;stdcall;
    implementation
    function test;extrnal 'dll.dll' name 'test';
    可以试试,不过看你的导出,如果用__declspec(dllexport)可能不能导出正确的函数名,最好用*.DEF定义,注意大小写!
      

  3.   

    function test(CharArray:PChar;Len:integer):pchar;stdcall;
    implementation
    function test;extrnal 'dll.dll' name 'test';
    可以试试,不过看你的导出,如果用__declspec(dllexport)可能不能导出正确的函数名,最好用*.DEF定义,注意大小写!
      

  4.   

    我调试过了,它能够调用dll,但是调用服务时却出错,我现在怀疑是dephi调用数组的问题。是不是类型上有什么不匹配的地方啊,dll是别人写的,我不能改的。只能在dephi客户端作处理,能帮我解答吗?
      

  5.   

    我以前写过这样的服务,试了一下你的程序,测试时候发现rel的值试SOAP:server表明服务调用已经成功了。我看主要有两种原因,一是调用方式不对,把StdCall改成Cdel。其次,就是不用pchar数组,用指针的Pchar类型,你试一试。