virConnectCreateXML doest seem to work for me
i created the following program and compiled it but it seems some linking problems or some kind of problem so i get these error
me.cpp: In function ‘int main(int, char**)’:
me.cpp:21:45: error: ‘virConnectCreateXML’ was not declared in this scope
dom = virConnectCreateXML(conn, xmlconfig, 0);
^
me.cpp:24:5: error: return-statement with no value, in function returning ‘int’ [-fpermissive]
return;
^
me.cpp:26:57: error: ‘virDomainName’ was not declared in this scope
fprintf(stderr, "Guest %s has booted", virDomainName(dom));
^
Program:
/* example ex9.c */
/* compile with: gcc -g -Wall ex9.c -o ex9 -lvirt */
#include <stdio.h>
#include <stdlib.h>
#include <libvirt/libvirt.h>
int main(int argc,char *argv[]){virConnectPtr conn;
char *host;
conn = virConnectOpen("qemu:///system");
if (conn == NULL) {
fprintf(stderr, "Failed to open connection to qemu:///system\n");
return 1;
}
virDomainPtr dom;
const char *xmlconfig = "<domain type='kvm'>
<name>win7</name>
<uuid>3666e50e-c616-42eb-aec8-b7fb1ad5f8f9</uuid>
<memory unit='KiB'>2072576</memory>
<currentMemory unit='KiB'>2072576</currentMemory>
<vcpu placement='static'>2</vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-2.5'>hvm</type>
<boot dev='hd'/>
</os>
<features>
<acpi/>
<apic/>
<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
</hyperv>
<vmport state='off'/>
</features>
<cpu mode='host-model'>
<model fallback='allow'/>
</cpu>
<clock offset='localtime'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
<timer name='hypervclock' present='yes'/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>restart</on_crash>
<pm>
<suspend-to-mem enabled='no'/>
<suspend-to-disk enabled='no'/>
</pm>
<devices>
<emulator>/usr/sbin/qemu-system-x86_64</emulator>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/win7.qcow2'/>
<target dev='hda' bus='ide'/>
<address type='drive' controller='0' bus='0' target='0' unit='0'/>
</disk>
<disk type='file' device='cdrom'>
<driver name='qemu' type='raw'/>
<source file='/home/dravigon/win7.iso'/>
<target dev='hdb' bus='ide'/>
<readonly/>
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
</disk>
<controller type='usb' index='0' model='ich9-ehci1'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x7'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci1'>
<master startport='0'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0' multifunction='on'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci2'>
<master startport='2'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x1'/>
</controller>
<controller type='usb' index='0' model='ich9-uhci3'>
<master startport='4'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x2'/>
</controller>
<controller type='pci' index='0' model='pci-root'/>
<controller type='ide' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
</controller>
<controller type='virtio-serial' index='0'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
</controller>
<interface type='direct'>
<mac address='52:54:00:56:27:95'/>
<source dev='enp3s0' mode='bridge'/>
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
<serial type='pty'>
<target port='0'/>
</serial>
<console type='pty'>
<target type='serial' port='0'/>
</console>
<channel type='spicevmc'>
<target type='virtio' name='com.redhat.spice.0'/>
<address type='virtio-serial' controller='0' bus='0' port='1'/>
</channel>
<input type='tablet' bus='usb'/>
<input type='mouse' bus='ps2'/>
<input type='keyboard' bus='ps2'/>
<graphics type='spice' autoport='yes'>
<image compression='off'/>
</graphics>
<sound model='ich6'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
</sound>
<video>
<model type='vga' vram='16384' heads='1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
</video>
<redirdev bus='usb' type='spicevmc'>
</redirdev>
<redirdev bus='usb' type='spicevmc'>
</redirdev>
<memballoon model='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
</memballoon>
</devices>
</domain>";
dom = virConnectCreateXML(conn, xmlconfig, 0);
if (!dom) {
fprintf(stderr, "Domain creation failed");
return;
}
fprintf(stderr, "Guest %s has booted", virDomainName(dom));
virDomainFree(dom);
virConnectClose(conn);
return 0;
}
help is thanked in advance
yeah found out the problem the functions
virConnectCreateXML
and its relaced by virDomainCreateXML function
Related
Disclaimer : I am pretty new to UI and QT.
I have UI that have QListWidget comprising of some numbers (1 to 5), now I am trying to delete the item one by one..
Problem :
After deletion of all entries are done, I can still see some entries (specifically 2 & 4).
Code:
File : main.cpp
Here I have created one async thread that will call MainWindows::display function.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
static MainWindow w;
w.show();
std::thread([]{
w.display();
}).detach();
a.exec();
return 0;
}
File : mainwindow.cpp
Here display function is deleting the items.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::display()
{
sleep(15);
for(int i = 0; i < 5 ; i++)
{
auto j = ui->listWidget->takeItem(i);
delete j;
}
}
MainWindow::~MainWindow()
{
delete ui;
}
File : mainwindow.UI
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>180</x>
<y>20</y>
<width>256</width>
<height>192</height>
</rect>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>19</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
Output:
Questions:
Why this is happening? am I doing something wrong?
If this leads to undeletion/corruption is there any other way to achieve it?
Any help is very much appreciated.
The reason is not really related to Qt but has to do with arrays and loops in general.
Say, initially, I start with a list:
0. Apple
1. Orange
2. Jackfruit
I remove the item at index 0:
0. Orange
1. Jackfruit
Now in the loop, we do i++, and then remove the item at index 1.
0. Orange
Notice that we completely skipped Orange because it moved down as we incremented our index.
If you want to delete everything, you can use QListWidget::clear() instead.
As for memory "corruption", the delete j is ok, since you need to manage the pointer yourself after calling takeItem.
On a side note, I wouldn't mix std::thread with Qt (see comments here).
I wrote a simple program using GTK and glade to allow the user to enter a number in a GtkSpinButton. Once the user hits the enter key (activate signal) the global variable should be changed to whatever the user entered in. Unfortunately that doesn't work and when I print out the global variable in the main function it simply spits out a zero. When I did this same thing with a string and a GtkEntry box it worked just fine. Here is the source code:
//gtkspinbox test program
// g++ -rdynamic -c lol.cpp $(pkg-config --cflags --libs gtk+-3.0 gmodule-2.0)
// g++ lol.o -o lol $(pkg-config --cflags --libs gtk+-3.0 gmodule-2.0)
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include <math.h>
#include <ctype.h>
using namespace std;
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <iomanip>
#include <limits>
#include <cmath>
#include <regex>
GtkWidget *lolwindow;
GtkWidget *lolfixed;
GtkWidget *lolentry;
GtkBuilder *builder;
int lol;
extern "C" void on_lolentry_activate(GtkEntry *e, gpointer user_data){
lol = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lolentry));
gtk_widget_destroy(lolwindow);
}
int main(int argc, char **argv){
gtk_init(&argc, &argv);//initializes gtk
builder = gtk_builder_new_from_file ("lol.glade");//reads the xml file generated by glade
gtk_builder_connect_signals(builder, NULL);
lolwindow = GTK_WIDGET(gtk_builder_get_object(builder, "lolwindow"));
g_signal_connect(lolwindow, "destroy", G_CALLBACK(gtk_main_quit), NULL);
lolfixed = GTK_WIDGET(gtk_builder_get_object(builder, "lolfixed"));
lolentry = GTK_WIDGET(gtk_builder_get_object(builder, "lolentry"));
gtk_widget_show(lolwindow);
gtk_main();
cout << lol << "\n";
}
and the glade file
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">1</property>
<property name="upper">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkWindow" id="lolwindow">
<property name="can_focus">False</property>
<property name="title" translatable="yes">enter a number lmao</property>
<child type="titlebar">
<placeholder/>
</child>
<child>
<object class="GtkFixed" id="lolfixed">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkSpinButton" id="lolentry">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
<signal name="activate" handler="on_lolentry_activate" swapped="no"/>
</object>
<packing>
<property name="x">161</property>
<property name="y">95</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Thanks for the help!
Apparently the maximum value of the adjustment variable in glade was set to zero and that's why the global variable was being set to zero. Once I entered a different value for the maximum value the problem went away.
Working with the buttons and handling its events is easy but I couldn't interact with progress bars. How do I get a Gtk::ProgressBar from a Glade file and set its fraction?
I use Gtkmm 3.24 and I want to update a progress bar when I click a button. here is my glade file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkApplicationWindow" id="MainWindow">
<property name="can-focus">False</property>
<property name="title" translatable="yes">My Main Window</property>
<property name="default-width">200</property>
<property name="default-height">150</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="LittleButton">
<property name="label" translatable="yes">button</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkProgressBar" id="MyProgressBar">
<property name="visible">True</property>
<property name="can-focus">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
My main.cpp file
#include <memory>
#include <gtkmm.h>
class MainWindow : public Gtk::ApplicationWindow
{
public:
MainWindow(BaseObjectType* obj, Glib::RefPtr<Gtk::Builder> const& builder)
: Gtk::ApplicationWindow(obj)
, builder{builder}
{
}
virtual ~MainWindow() = default;
private:
Glib::RefPtr<Gtk::Builder> builder;
};
int main(int argc, char* argv[])
{
auto app = Gtk::Application::create(argc, argv, "de.engelmarkus.example");
auto builder = Gtk::Builder::create_from_file("MyGladeGUI.glade");
MainWindow* mwindow = nullptr;
builder->get_widget_derived("MainWindow", mwindow);
auto littleButton = builder->get_object("LittleButton");
auto r = app->run(*mwindow);
delete mwindow;
return r;
}
I build my application from the command line with:
g++ -rdynamic main.cpp -o hello $(pkg-config gtkmm-3.0 --libs --cflags)
Here is code that does what you want:
#include <memory>
#include <gtkmm.h>
constexpr int ERROR = 1;
int main(int argc, char* argv[])
{
auto app = Gtk::Application::create(argc, argv, "de.engelmarkus.example");
auto builder = Gtk::Builder::create_from_file("MyGladeGUI.glade");
// Get the window. First a `Glib::Object` handle to it and then cast it
// to the `Gtk::ApplicationWindow` type:
Glib::RefPtr<Glib::Object> mainWindowAsObject = builder->get_object("MainWindow");
Glib::RefPtr<Gtk::ApplicationWindow> mainWindow = Glib::RefPtr<Gtk::ApplicationWindow>::cast_dynamic(mainWindowAsObject);
if(!mainWindow)
{
return ERROR;
}
// At this point, the main window is valid, and as bonus, wrapped in a smart
// pointer, which means you do not have to manage its memory yourself. Now get
// the button. First get a `Glib::Object` handle to it and then cast it to the
// `Gtk::Button` type:
Glib::RefPtr<Glib::Object> buttonAsObject = builder->get_object("LittleButton");
Glib::RefPtr<Gtk::Button> button = Glib::RefPtr<Gtk::Button>::cast_dynamic(buttonAsObject);
if(!button)
{
return ERROR;
}
// At this point, the button is valid. We have to get the progress bar. You get
// the idea now ;):
Glib::RefPtr<Glib::Object> pBarAsObject = builder->get_object("MyProgressBar");
Glib::RefPtr<Gtk::ProgressBar> pBar = Glib::RefPtr<Gtk::ProgressBar>::cast_dynamic(pBarAsObject);
if(!pBar)
{
return ERROR;
}
// At this point, both the button and the progress bar have been extracted
// from the builder and are valid. We can now connect the button's 'clicked'
// signal handler:
button->signal_clicked().connect([&pBar](){
const double currentFraction = pBar->get_fraction();
pBar->set_fraction(currentFraction + 0.10);
});
// The syntax is ugly the basically:
// 1. Call `get()` to retreive the stored pointer
// 2. Call operator* on this pointer to get a reference
return app->run(*(mainWindow.get()));
} // mainWindow automatically deleted here by its RefPtr container!
Output:
I have taken the liberty to simplify it a bit. Most importantly, I reviewed your memory management model and completely removed the usage of delete, through the use of Glib::RefPtr which can do that for you.
You can build with:
g++ -rdynamic main.cpp -o hello `pkg-config gtkmm-3.0 --libs --cflags`
Note: I wrote this using Gtkmm 3.22.
I'm trying to write a pro-forma ISAPI extension in an attempt to better understand IIS. I have the following code for the exension:
#include <httpext.h>
#include <cstring>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <windows.h>
BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO * versionInfo)
{
versionInfo->dwExtensionVersion = HSE_VERSION;
strcpy_s( versionInfo->lpszExtensionDesc, "ISAPIExtension.dll");
return TRUE;
}
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK* ecb)
{
char * msg = "<html><head/><body>Hello world</body></html>";
DWORD msg_length = strlen(msg) * sizeof(char);
DWORD sent_length = msg_length;
std::cout << sent_length;
auto result = ecb->WriteClient(ecb->ConnID, msg, &sent_length, 0);
if (!result || sent_length != msg_length)
{
std::fstream output("errors.txt");
output << "Could not write to client. Last error was " << GetLastError();
output.flush();
output.close();
return HSE_STATUS_ERROR;
}
std::cout << sent_length;
return HSE_STATUS_SUCCESS;
}
IIS Express responds with HTTP 200, but zero bytes were sent back to the client. Is anything in the above wrong? For reference, this is my applicationhost.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<configSections>
<sectionGroup name="system.applicationHost">
<section name="applicationPools"/>
<section name="sites"/>
</sectionGroup>
<sectionGroup name="system.webServer">
<section name="globalModules"/>
<section name="handlers"/>
<section name="caching"/>
<section name="modules"/>
<section name="staticContent"/>
<section name="httpErrors"/>
<sectionGroup name="tracing">
<section name="traceFailedRequests" overrideModeDefault="Allow" />
<section name="traceProviderDefinitions" overrideModeDefault="Deny" />
</sectionGroup>
<!-- The following section elements are not specified in this file, but without these
declarations, IIS will 500 requests -->
<sectionGroup name="security">
<section name="isapiCgiRestriction"/>
<section name="access"/>
<sectionGroup name="authentication">
<section name="anonymousAuthentication"/>
</sectionGroup>
</sectionGroup>
<section name="serverRuntime"/>
</sectionGroup>
</configSections>
<system.applicationHost>
<applicationPools>
<add name="UnmanagedClassicAppPool" managedRuntimeVersion="" managedPipelineMode="Classic" autoStart="true" />
</applicationPools>
<sites>
<site name="Default Web Site" id="1" serverAutoStart="true">
<application path="/" applicationPool="UnmanagedClassicAppPool">
<virtualDirectory path="/" physicalPath="%IIS_USER_HOME%\blog" />
</application>
<bindings>
<binding protocol="http" bindingInformation=":8080:localhost" />
</bindings>
<traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" maxLogFileSizeKB="1024" />
</site>
</sites>
</system.applicationHost>
<system.webServer>
<security>
<isapiCgiRestriction notListedIsapisAllowed="true"/>
</security>
<globalModules>
<add name="StaticFileModule" image="%IIS_BIN%\static.dll" />
<add name="AnonymousAuthenticationModule" image="%IIS_BIN%\authanon.dll" />
<add name="IsapiModule" image="%IIS_BIN%\isapi.dll" />
<add name="FailedRequestsTracingModule" image="%IIS_BIN%\iisfreb.dll" />
</globalModules>
<staticContent>
<mimeMap fileExtension=".html" mimeType="text/html" />
</staticContent>
<modules>
<add name="StaticFileModule"/>
<add name="AnonymousAuthenticationModule"/>
<add name="IsapiModule"/>
<add name="FailedRequestsTracingModule"/>
</modules>
<handlers accessPolicy="Read, Execute, Script">
<add name="ISAPI-dll" path="*.dll" verb="*" modules="IsapiModule" resourceType="File" requireAccess="Execute" allowPathInfo="true" />
<add name="StaticFile" path="*.html" verb="*" modules="StaticFileModule" resourceType="Either" requireAccess="Read" />
</handlers>
<tracing>
<traceProviderDefinitions>
<add name="ISAPI Extension" guid="{a1c2040e-8840-4c31-ba11-9871031a19ea}">
<areas>
<clear />
</areas>
</add>
</traceProviderDefinitions>
<traceFailedRequests>
<add path="*">
<traceAreas>
<add provider="ISAPI Extension" verbosity="Verbose" />
</traceAreas>
<failureDefinitions statusCodes="200-999" />
</add>
</traceFailedRequests>
</tracing>
</system.webServer>
</configuration>
Adding a Content-Type header fixes the issue:
DWORD WINAPI HttpExtensionProc(EXTENSION_CONTROL_BLOCK* ecb)
{
char msg [] = "<html><head/><body>Hello world</body></html>";
DWORD msg_length = strlen(msg);
DWORD sent_length = msg_length;
HSE_SEND_HEADER_EX_INFO HeaderExInfo;
HeaderExInfo.pszStatus = "200 OK";
HeaderExInfo.pszHeader = "Content-type: text/html\r\n\r\n";
HeaderExInfo.cchStatus = strlen(HeaderExInfo.pszStatus);
HeaderExInfo.cchHeader = strlen(HeaderExInfo.pszHeader);
HeaderExInfo.fKeepConn = FALSE;
ecb->ServerSupportFunction(ecb->ConnID, HSE_REQ_SEND_RESPONSE_HEADER_EX, &HeaderExInfo, NULL, NULL);
auto result = ecb->WriteClient(ecb->ConnID, msg, &sent_length, 0);
if (!result || sent_length != msg_length)
{
return HSE_STATUS_ERROR;
}
return HSE_STATUS_SUCCESS;
}
Microsoft has posted a similar ISAPI extension sample on their GitHub account: https://github.com/Microsoft/Windows-classic-samples/tree/master/Samples/Win7Samples/web/iis/extensions/simple
I am trying to build a server application using gsoap 2.8.17. I've created a header file with service function prototype and a result record definition
testserver.h:
#ifndef TESTSERVER_H
#define TESTSERVER_H
#include <string>
//gsoap ns service name: TestServer
//gsoap ns service namespace: http://mycomp:8080/TestServer.wsdl
//gsoap ns service location: http://mycomp:8080/TestServer.cgi
//gsoap ns schema namespace: urn:TestServer
class Record
{
public:
int id;
std::string name;
std::string address;
double param1;
};
int ns__GetRecord(int id, Record* result);
#endif
Then I've invoked the gSOAP RPC compiler:
soapcpp2.exe testserver.h
The compiler produced the following files:
soapC.cpp
soapClient.cpp
soapClientLib.cpp
soapServer.cpp
soapServerLib.cpp
soapH.h
soapStub.h
TestServer.h
TestServer.nsmap
TestServer.wsdl
TestServer.GetRecord.req.xml
TestServer.GetRecord.res.xml
ns.xsd
TestServer.wsdl
<?xml version="1.0" encoding="UTF-8"?>
<definitions name="TestServer"
targetNamespace="http://mycomp:8080/TestServer.wsdl"
xmlns:tns="http://mycomp:8080/TestServer.wsdl"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="urn:TestServer"
xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:HTTP="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/"
xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<schema targetNamespace="urn:TestServer"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns="urn:TestServer"
xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="unqualified"
attributeFormDefault="unqualified">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="Record"><!-- Record -->
<sequence>
<element name="id" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- Record::id -->
<element name="name" type="xsd:string" minOccurs="1" maxOccurs="1"/><!-- Record::name -->
<element name="address" type="xsd:string" minOccurs="1" maxOccurs="1"/><!-- Record::address -->
<element name="param1" type="xsd:double" minOccurs="1" maxOccurs="1"/><!-- Record::param1 -->
</sequence>
</complexType>
<!-- operation request element -->
<element name="GetRecord">
<complexType>
<sequence>
<element name="id" type="xsd:int" minOccurs="1" maxOccurs="1"/><!-- ns__GetRecord::id -->
</sequence>
</complexType>
</element>
<!-- operation response element -->
<element name="GetRecordResponse">
<complexType>
<sequence>
<element name="result" type="ns:Record" minOccurs="0" maxOccurs="1" nillable="true"/><!-- ns__GetRecord::result -->
</sequence>
</complexType>
</element>
</schema>
</types>
<message name="GetRecordRequest">
<part name="Body" element="ns:GetRecord"/><!-- ns__GetRecord::ns__GetRecord -->
</message>
<message name="GetRecordResponse">
<part name="Body" element="ns:GetRecordResponse"/>
</message>
<portType name="TestServerPortType">
<operation name="GetRecord">
<documentation>Service definition of function ns__GetRecord</documentation>
<input message="tns:GetRecordRequest"/>
<output message="tns:GetRecordResponse"/>
</operation>
</portType>
<binding name="TestServer" type="tns:TestServerPortType">
<SOAP:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetRecord">
<SOAP:operation soapAction=""/>
<input>
<SOAP:body parts="Body" use="literal"/>
</input>
<output>
<SOAP:body parts="Body" use="literal"/>
</output>
</operation>
</binding>
<service name="TestServer">
<documentation>gSOAP 2.8.17 generated service definition</documentation>
<port name="TestServer" binding="tns:TestServer">
<SOAP:address location="http://mycomp:8080/TestServer.cgi"/>
</port>
</service>
</definitions>
As documentation recommends I added soapServerLib.cpp to my project, but the C++ Builder 2010 compiler produces errors:
[BCC32 Error] soapC.cpp(1611): E2238 Multiple declaration for 'ns__GetRecord(soap *,int,Record *)'
[BCC32 Error] soapStub.h(224): E2344 Earlier declaration of 'ns__GetRecord(soap *,int,Record *)'
[BCC32 Error] soapC.cpp(1611): E2303 Type name expected
[BCC32 Error] soapC.cpp(1611): E2379 Statement missing ;
[BCC32 Error] soapC.cpp(1717): E2379 Statement missing ;
soapStub.h(224):
SOAP_FMAC5 int SOAP_FMAC6 ns__GetRecord(struct soap*, int id, Record *result);
soapC.cpp(1598-1619):
SOAP_FMAC1 struct ns__GetRecord * SOAP_FMAC2 soap_instantiate_ns__GetRecord(struct soap *soap, int n, const char *type, const char *arrayType, size_t *size)
{
(void)type; (void)arrayType; /* appease -Wall -Werror */
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_instantiate_ns__GetRecord(%d, %s, %s)\n", n, type?type:"", arrayType?arrayType:""));
struct soap_clist *cp = soap_link(soap, NULL, SOAP_TYPE_ns__GetRecord, n, soap_fdelete);
if (!cp)
return NULL;
if (n < 0)
{ cp->ptr = (void*)SOAP_NEW(struct ns__GetRecord);
if (size)
*size = sizeof(struct ns__GetRecord);
}
else
{ cp->ptr = (void*)SOAP_NEW_ARRAY(struct ns__GetRecord, n); // <<<-- error here
if (size)
*size = n * sizeof(struct ns__GetRecord);
}
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Instantiated location=%p\n", cp->ptr));
if (!cp->ptr)
soap->error = SOAP_EOM;
return (struct ns__GetRecord*)cp->ptr;
}
Why is ns__GetRecord interpreted as a structure while it's a function name? What should I fix in my TestServer.h to make soapcpp2.exe produce a compilable code ?
The only solution I found is to remove the soap_instantiate_ns__GetRecord function body.
SOAP_FMAC1 struct ns__GetRecord * SOAP_FMAC2 soap_instantiate_ns__GetRecord(struct
soap *soap, int n, const char *type, const char *arrayType, size_t *size)
{
return NULL;
}
Then the server code compiles and works fine.