Solved

midl.exe does not accept  function definition

Posted on 2000-03-09
8
1,588 Views
Last Modified: 2012-08-14
I was able to compile this code with idltojava (without the uuid info), but it gives me syntax errors when I use midl.exe.  am I missing something in the beginning of the code?

// here is my code
[ uuid (53D5C100-25F6-11D1-B64C-000012df6b3e),
  version(1.0),
  pointer_default(unique)
]
interface Hello
{
    struct A {short field;};
    const float pi = 3.14;
    void f();
    void q(in long s); // it fails in this line
};

//here's the error message
error MIDL2025 : syntax error : expecting a type specification near "in"
0
Comment
Question by:tekel
  • 4
  • 2
  • 2
8 Comments
 
LVL 1

Expert Comment

by:Andy_Keys
ID: 2601241
try [in] instead of in and see if that works
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2601273
Try void q([in] long s);
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2601274
hm.
0
 
LVL 1

Expert Comment

by:Andy_Keys
ID: 2601287
at least we agree!!
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:tekel
ID: 2601361
okay, using [in] works when i use midl.exe,
but when I use idltojava it gives me a syntax error in the same line.  I thought IDL was suppose to be language-independent?
0
 
LVL 5

Expert Comment

by:Wyn
ID: 2601414
midl is microsoft specific.
0
 
LVL 5

Accepted Solution

by:
Wyn earned 60 total points
ID: 2601445
Microsoft Interface Definition Language (MIDL): 64-Bit
Porting Guide

Microsoft Corporation

Last updated: August 1999

Summary: This technical white paper discusses
Microsoft?Interface Definition Language (MIDL)
compiler
and Remote Procedure Call (RPC) issues related to
64-bit porting efforts. Both old techniques and new
64-bit features that can facilitate porting
applications from 32-bit environments are described.

Contents

Introduction
Issues
Tips for Modifying RPC Interfaces
MIDL64—New Features for 64-Bit Windows
Frequently Asked Questions
Open Issues
For More Information

Introduction

This technical white paper discusses Microsoft?
Interface Definition Language (MIDL) compiler and
Remote
Procedure Call (RPC) issues related to 64-bit porting
efforts. Both old techniques and new 64-bit features
that can facilitate porting applications from 32-bit
environments are described.

Summary

With the coming availability of 64-bit Windows?there
is a need for a MIDL/RPC guide outlining what can
and cannot be done with regards to porting legacy
applications.

   Terminology Note   There is some confusion among IT
staff regarding the terms local, inproc and
   remote. An inproc call in RPC means an RPC call
that is executed within the same process. For
   example, different DCOM apartments can execute as
separate threads in a process. RPC is optimized
   for in-process calls; however, the arguments of the
call still go through the marshaler. Therefore, all
   the usual restrictions of RPC calls, such as no
void *, apply. The inproc call category has been
   introduced for performance reasons, as some handles
make sense on both sides of the call. Remote
   call usually refers to a non-inproc call, because
there is not a much difference between executing an
   RPC call from process to process or from machine to
machine. Both cases involve two different address
   spaces requiring marshaling of all the arguments.
Sometimes, especially in contrast to a local call, a
   remote call means any call that goes through RPC
and so requires marshaling and unmarshaling of
   arguments. In RPC context, a local call means a
call within the same process where RPC is actually not
   used at all—the call goes directly from client
layer to server layer of the application. In
particular, a
   [local] attribute of RPC means that the procedure
or interface flagged with it is never used in a remote
   call. Sometimes an interface is specified as
[local] just to get its C definition in a convenient
..h file.

   Also note, that when more information about
specific MIDL attributes is desired, MSDN is the best
up
   to date source for pre-64-bit functionality RPC
documentation.

Issues

This section focuses on 64-bit specific problems;
discussion of 32-bit specifics has been added where
appropriate.

Backward Wire Compatibility

When porting an RPC application, the key feature to
consider is the backward wire compatibility; that is,
the ability of the original and the ported versions to
talk in the same wire format or protocol, in this case
the NDR (see Endnote 1) wire representation of
transmitted data. Backward wire compatibility may be
an
issue whenever one of the following happens:

     Methods are added to an interface.

     New data types are introduced.

     Old data types are changed in some way.

Usually, methods are added to the interface as a
result of expanding the server's functionality for a
new
release of a product. The wire incompatibility may
happen if the new client is not prevented from calling
the
old server. This type of wire incompatibility is the
most obvious one, and this issue is not really a
porting
issue; see the section "Nonissues" for a more detailed
discussion.

Introducing a new data type or modifying an existing
data type is the most frequent source of wire
incompatibility problems. The core reason for all of
these problems is that the OSF/DCE RPC paradigm
assumes that the receiving party has preexisting
knowledge about the nature of the data coming in; that
is, the data is sent without a generic data
description. Therefore, whenever a receiver expects a
different
data type than the sender has put on the wire, the
most likely outcome is a bad stub data exception.

The cleanest way of adding new data types to an
interface is to use them only in new methods. This
doesn't create any problems other than the ones
introduced by adding the new methods themselves.
Changing data types used in existing methods creates
incompatibilities. Typically, there are two ways to
add types to an existing interface that can create
problems. The explicit way is to change one of the
unions controlling data flow by defining a new branch
that takes a new type, such as a new info level in
some methods returning server information. This is
usually a situation that is easy to control. The
change,
however, may be concealed when an application hides a
data type from RPC or cheats on the RPC
marshaler. An example of hiding is when an application
sends an array of bytes that, in fact, is structured
data. An example of cheating is when an application
sends a long that means something else. Hiding is
actually a form of cheating, and application writers
usually encounter trouble when the application talks
to
a big-endian machine for the first time.

Porting from the 32-bit version of Windows to Win64?
does not create RPC problems in itself. The
abstract data type model established for porting (that
is, LLP64) has a great advantage for porting RPC
applications. Essentially, in this model, all of the
integral data types used in the 32-bit world stay at
the
same size in the 64-bit world, and only the pointer
size changes from 32-bit to 64-bit. The RPC
programming model has always relied on data sizes
being well defined, with all of the integral types
being
the same size on both sides of the connection. Because
the size of the integral types doesn't change,
there is no wire incompatibility. On the other hand,
pointers are local to each side of the RPC
transmission
and typically go on the wire only as null or nonnull
markers. Thus, marshaler is able to handle different
pointer sizes on both ends of a connection in a manner
that is transparent to the user.

Nonissues

Pointers, when specified

Changing the size of the pointer itself is not an
issue if the interface in question has a pointer
specified as
an argument. On the wire, pointers are represented by
4-byte markers. When making an RPC, whether it
is truly remote or within the same machine, pointers
are typically recreated from scratch at the other
side,
based on the marker. The MIDL and RPC marshaler handle
this transparently. For 64-bit porting, this
transparent handling is at the expense of performance.
Performance extensions to the MIDL compiler and
the corresponding marshaler engine are planned for the
future.

Also note that a typical pointer for an [in] argument,
such as the one shown below:

   long  Foo( [in] long * Bar );

is a [ref] pointer that does not have any wire
representation at all. In the above example,
only a long would be sent from client to server.

Context handles

The context handle is a special RPC concept introduced
solely for the purpose of giving a client an opaque
handle to a server context held on behalf of the
client. Typically, it is a void * pointer marked as a
context
handle. The type is defined with the [context_handle]
attribute and implies the following semantics. A
handle must be obtained from the server first,
typically by means of a call with handle as an [out]
argument. The client indicates the context whenever
handle is an [in] argument. At the end, the handle
must be closed to clean up the server context. This is
done by means of a call with an [in,out] context
handle argument when the handle comes back as null. An
added bonus is that a context handle can be
cleaned up automatically by the RPC runtime when the
connection breaks.

Each context is identified by a globally unique
identifier (GUID) generated on the fly by the RPC
runtime
when the handle is created. Context handles are
represented on the wire by 20 bytes that include the
GUID to identify the context. On the client, the
application is handed a handle to a dictionary storing
the
context handle GUIDs. On the server, the pointer to
the context is retrieved from a similar dictionary
based on the GUID. No pointer is sent across, and this
process works completely transparently across the
32-bit/64-bit boundary.

For example:

typedef [context_handle] void * MyContext;

void OpenContext( <some other args>,  [out] MyContext
* pHandle );
void UseContext( [in] MyContext  Handle, <some other
args>  );
void CloseContext( [in,out] MyContext * pHandle );  //
null when [out]

One important part of context handle semantics is that
a context handle is related to the
server that generated it. In particular, when there is
no explicit binding handle argument
of a call, the context handle argument directs the
binding, meaning that the call is
directed to the server that originated the handle. If
an explicit binding handle is used, the
binding implied by the context handle must agree with
the one indicated by the binding
handle, and must resolve to the same server. If there
is a disagreement—for example, if
different servers are implied by context handle(s) and
the binding handle—the call fails by
definition.

In addition, there is a group of attributes related to
context handles that can force a better granularity of
the context checking or some particular type of a
context handle; this is outside of the scope of this
discussion. For example, a programmer can specify a
[strict_context_handle] type, where the context
handle is valid only when used with the same server
and interface that created it.

Handle Types

Binding handles, handle_t type

These handles are RPC handles indicating the server to
connect to. They are indicated by the application
configuration file (ACF) attributes, such as
[implicit_handle], [explicit_handle], and
[auto_handle]. These
handles are internal RPC handles that are never
represented as arguments on the wire. They are
manipulated by means of RPC runtime application
programming interfaces (APIs), and not by remote
calls.
Typically, a handle must be well-defined before a
remote call can be executed and doesn't change during
the call. Other internal RPC handles of a similar
nature are pickling handles and async handles.

Generic [handle] handles

A generic handle is a special type of binding handle
that is a cross between a binding handle and a generic
data type remotable by means of RPC. When this type of
handle is used in a call, special binding semantics
are implied (on the client side only) by the stub
before and after the proper remote call. A typical
declaration may look like this:

typedef [handle] wchar_t *STRING_HANDLE;

It's used in a call like this:

DWORD
RpcOpenPrinter(
   [in, string, unique] STRING_HANDLE pPrinterName,
   [out] PRINTER_HANDLE *pHandle,
   [in, string, unique] wchar_t * pDatatype,
   [in] LPDEVMODE_CONTAINER pDevMode,
   [in] DWORD AccessRequired
);

The special binding semantics consist of the client
stub calling a STRING_HANDLE_bind()
routine to establish a binding before the stub
marshals arguments, then calling a
STRING_HANDLE_unbind() routine after the stub
unmarshals the reply. The application
writer provides the routines. The bind and unbind
calls are performed each time the client
application executes a call using a STRING_HANDLE
argument as a binding argument.

When data is marshaled for the call, the generic
handle argument is represented by the data it has been
specified with. Therefore, it is undistinguishable on
the wire from the same data being sent in the usual
way. As far as the data itself is concerned, it is
treated like other data arguments for the purposes of
marshaling and unmarshaling. In the above example, a
Unicode character string would be marshaled as
usual for a STRING_HANDLE argument.

INT_PTR, LONG_PTR

Each of these is a polymorphic integral type that has
a different size on 32-bit and 64-bit Windows NT?
platforms to guarantee that a pointer value can be
stored in it. The data types are defined in the public
file, basetsd.h. Each has a size of 4 bytes on 32-bit
systems and 8 bytes on 64-bit systems. On 32-bit
platforms, INT_PTR maps to int and LONG_PTR maps to
long. On 64-bit platforms, both the types map to
__int64. Types such as these cannot be supported in a
satisfactory way in RPC. In fact, if not for the
porting, a type like this would never be supported and
should be seen only as a means of facilitating the
32-bit-to-64-bit porting effort. The reason these
types are supported by MIDL is to address a situation
where a pointer needs to be kept in an integral field
for some reason. Typically, a remote application
programming interface (API) would send a handle across
the wire disguised as a DWORD.

Please note however, that sending a pointer or handle
this way could never really work with RPC. That is,
either the argument didn't mean a pointer, it went
unused, or the pointer or handle value was sent out
only to be sent back and used at the server. In other
words, this was another case of cheating on RPC. As
described in this document, one way to avoid cheating
is to use a context handle or an IUnknown interface
pointer.

MIDL supports the 32-bit/64-bit polymorphism by means
of the __int3264 intrinsic integral type described
later in this document. However, this type should not
be introduced to a remoted interface unless it is
unavoidable because of porting. New interfaces should
never use it. You should make up your mind as to
the nature of data manipulated remotely and specify
either an __int32 (a long) or an __int64 (a hyper) as
appropriate. If the field or argument is really
designed to hold a pointer, an appropriate pointer or
context
handle type should be used.

For the porting, you should not use the new intrinsic.
Instead, you should use the types defined in
public\sdk\inc\basetsd.h directly: INT_PTR, LONG_PTR,
DWORD_PTR, and so forth, can be used as
appropriate. The file contains all the mappings needed
for MIDL and C/C++ compilation of the types.

The polymorphic types should not be used
automatically, just because they are available. For
clarity of
design and implementation, it is worth reworking the
application so that you use clean types and thereby
avoid side effects, such as the performance penalty
inherent to polymorphic types.

For example, in RPC's own code, there was a case where
a BufferLength field was assigned a pointer
because the marshaler was using a sizing routine
(which increments a value of the BufferLength field by
an
object size according to the object type) to increment
the pointer by the size of the pointee. At first, it
seemed that this field needed to be converted from
unsigned long to UINT_PTR. Some alignment issues
had to be taken care of, but eliminating the usage was
fairly simple; therefore, modifying the application
removed the need to use the polymorphism at all.

Examples of Problems with Cheating

In summary, at the core of each RPC porting problem is
always an application not sticking to the RPC
specification and cheating on the stubs and marshaler
in some way.

Problems may typically arise when:

     A remoted data type changes for some reason. For
example, a field was a long and
     now needs to be __int64. See the LONG_PTR
description above for a discussion.

     Some kind of cheating on the core RPC marshaling
was taking place, and typically
     some side effects were used to send simplified
data for performance or other reasons.

Example 1. Sending a server pointer context back as a
DWORD in a standard interface

Typically, this is a design problem that should have
been solved by using context handles in the first
place.

For example:

CONFIGRET
RegisterNotification(
    [in]                     handle_t hBinding,
    [in]                     ULONG    hRecipient,
    [in,size_is(ulSize)]     LPBYTE  
NotificationFilter,
    [in]                     ULONG    ulSize,
    [in]                     DWORD    Flags,
    [out]                    PULONG   Context,
    [in]                     ULONG    hProcess
    );

CONFIGRET
UnregisterNotification(
    [in]                     handle_t hBinding,
    [in]                     ULONG    Context
    );

This is an excerpt from a standard (raw) RPC
interface, as opposed to an object or DCOM
interface.

Apparently ULONG sent as a context is intended to be a
pointer. Hence, that would not work when
sending back and forth from a 32-bit to a 64-bit
environment. Also note, that changing the type of the
Context argument from ULONG to __int64 or similar will
break the wire compatibility, and that using
__int3264, as described later, would keep wire
compatibility intact but would not work (the cheating
is not
good enough).

From what we know, the ULONG manipulated here is
really a server context handle—the handle is obtained
in the Register call and released in the Unregister
call above. We are not interested in details of the
handle
usage. However, notice that this design has an
inherent problem in that it is not clear what happens
with
the server context when the client dies or goes away
without unregistering first. This functionality should
have been mapped to a context handle solution. In
other words, the design is flawed because a shortcut
is used when sending context pointers instead of a
clean context handle.

When looking at a problem like this in the context of
porting, it is important to consider whether wire
compatibility is an issue. Your solution choice
depends on whether the interface has been made public;
if it
has, it generally cannot be changed. On the other
hand, if the interface was used only within a single
machine by a component that cannot have different
versions on the same machine, it typically can be
changed freely.

In many situations, it is possible that backward
compatibility problems can be ignored or the interface
reworked so that a context handle is used. If this is
possible, it is the best solution. To use context
handles, the interface could be changed to take the
following:

typedef [context_handle] void * NOTIFICATION_CONTEXT;

CONFIGRET
RegisterNotification(
    [in]                     handle_t hBinding,
    [in]                     ULONG    hRecipient,
    [in,size_is(ulSize)]     LPBYTE  
NotificationFilter,
    [in]                     ULONG    ulSize,
    [in]                     DWORD    Flags,
    [out]                    NOTIFICATION_CONTEXT *
pContext,
    [in]                     ULONG    hProcess
    );

CONFIGRET
UnregisterNotification(
    [in]                     handle_t hBinding,
    [in,out]                 NOTIFICATION_CONTEXT *
pContext
    );

The user needs to provide a rundown routine to clean
up the server context when the
connection between client and server breaks. The
routine would have the following
prototype:

void __RPC_USER NOTIFICATION_CONTEXT_rundown(
    NOTIFICATION_CONTEXT handle);

Please see description of context handles in the
context handle section for more
information about the Context_rundown routine.

Example 2. Sending a server pointer context back as a
DWORD in a DCOM interface

Typically, this is another design problem. Possibly,
IUnknown * should have been used. For example, let's
look at IConnectionPoint interface.

interface IConnectionPoint : IUnknown
{
    < snip, snip >

    HRESULT Advise(
                [in] IUnknown * pUnkSink,
                [out] DWORD * pdwCookie );

    HRESULT Unadvise(
                [in] DWORD dwCookie );

}

This is similar to the previous example in that, as
far as we know, the intention here was
to have the cookie be a polymorphic type that would
make it possible to send DWORDs as
well as pointers across the wire.

First, note that the interface is a public interface
released with Windows NT 4.0; therefore, backward wire
compatibility is required. For that reason, changing
the interface is not an option. If the interface
needed
to be changed, the only solution would be to introduce
another interface and phase out this one over
time.

Even if the backward compatibility requirement didn't
preclude changing the interface, the context handle
approach could not be used here. This is because DCOM
provides a context_handle-like functionality by its
nature. Therefore, context handles are not needed in
DCOM interfaces and MIDL would not allow using
one. One way of looking at this is that server
contexts correspond to objects in DCOM. So, instead of
creating a context handle, you pass an interface
pointer indicating the object. Instead of passing the
context handle to indicate the server context, you can
either call methods directly through the interface
pointer or you can put that interface pointer in some
other calls. Lastly, to release a server object the
client can simply call the Release() method, present
in every interface, through the interface pointer.
This is
the essence of object programming in DCOM—the contexts
(objects) are indicated by interface pointers
and reference counting dictates their life span.

Therefore, in DCOM, the typical solution is, in a way,
symmetrical to context handles in raw RPC, or, if you
prefer, context handles emulate an object behavior.
For this reason, the cookie should have been defined
as an IUnknown * pointer and the interface could have
read:

   
HRESULT Advise(
                [in] IUnknown * pUnkSink,
        [out] IUnknown ** ppCookie );

Note that the Unadvise method isn't needed at all; to
release the context it would be
enough to call:

   pCookie->Release();

As mentioned earlier, every interface has a Release()
method by virtue of inheriting from
the IUnknown interface.

Example 3. Sending a pointer as a DWORD

Continuing the previous example, whatever can be said
about errors of the original design, there may also
be a legacy problem. That is, there may be a situation
where a pointer was sent as a long, nothing can be
done without breaking wire compatibility, and some
other fix is needed. In this case, the solution would
be
to stick to the wrong design; that is, keep sending
the long, but do an auxiliary mapping between pointers
and DWORDs as necessary.

For example, the methods from the previous example
could be fixed by introducing a simple RPC wrapper
by means of using [call_as] attribute. (If your
application uses the standard RPC interface, see the
discussion of the [call_as] feature and the example of
usage with a standard RPC interface).

[local]
HRESULT Advise(
    [in]  IUnknown * pUnkSink,
    [out] DWORD_PTR * pdwCookie );

[local]  
  HRESULT Unadvise(
    [in] DWORD_PTR dwCookie );

[call_as(Advise)]
HRESULT NewRemoteAdvise(
    [in] IUnknown * pUnkSink,
    [out] DWORD *   pdwCookie );


[call_as(Unadvise)]
HRESULT NewRemoteUnadvise(
            [in] DWORD  dwCookie );

Note that the application interface has the same
methods, Advise and Unadvise, except
that they have to take an ULONG_PTR or DWORD_PTR
instead of DWORD to be able to
keep a pointer. As explained in the [call_as] section,
the call still goes through Advise and
Unadvise for application API compatibility, except
that the remote call is now executed
using the NewRemote* methods. For this particular
case, the new remote methods are
designed to have exactly the same wire layout. What
you get from the [call_as] scheme is
simply the introduction of hand-written wrappers on
both sides. The server side wrapper
for Advise needs to introduce mapping between the
returned pointers and DWORDs by
keeping an appropriate dictionary. A server wrapper
for Unadvise needs to map back from a
DWORD to pointer using the same dictionary. The client
side wrapper does not have to do
anything except pass the arguments without any
changes. Therefore, the wrappers could
look like this:

// server side wrappers
HRESULT
IConnectionPoint_Advise_Stub(
    IConnectionPoint * This,
IUnknown * pUnkSink,
DWORD * pdwCookie )
{
  LONG_PTR * UnmappedCookie = 0;
  HRESULT hr =
     This->lpVtbl->Advise( This, pUnkSink, &
UnmappedCookie );
  *pdwCookie = MapPointertoDWORD( UnmappedCookie );
  return hr; // add a better error control
}

HRESULT
IConnectionPoint_Unadvise_Stub (
    IconnectionPoint * This,
DWORD dwCookie )
{
  LONG_PTR Cookie = MapDWORDtoPointer( dwCookie);
  return This->lpVtbl->Unadvise( This, Cookie );
}

// client side wrappers
HRESULT
IconnectionPoint_Advise_Proxy(
    IConnectionPoint * This,
IUnknown * pUnkSink,
DWORD_PTR * pdwCookie )
{
  return IConnectionPoint_NewRemoteAdvise_Proxy( This,
pUnkSink,
                             (DWORD *)pdwCookie );
}

HRESULT
IconnectionPoint_Unadvise_Proxy (
    IConnectionPoint * This,
DWORD_PTR dwCookie )
{
  return IConnectionPoint_NewRemoteUnadvise_Proxy(
This, (DWORD)dwCookie );
}

Note that this is a porting solution; namely, in this
solution, we always do mapping
between cookies and DWORDs and we always send DWORDs
out. For 64-bit-to-64-bit
communications with better performance, a clean way to
cheat would be to simply define
another interface, one that would send an __int64 on
the wire.

Remoting Handles

In this section we discuss general issues related to
remoting handles as opposed to pointers. Please look
at the next section to see how to deal with Win32
system handles.

The essential difference here is that while a pointer
directly indicates a datum, a handle may be seen as a
key to data. That is, some level of indirection is
implied by the handle, some other special values of
the
handle can exist besides NULL, etc. If so, then the
implementor of the handle package may choose to
restrict the handle value range of 64b package to be
the same as the range of the 32b package, most
likely to be 32b key values. As 4GB range implies a
lot of handles, this is most likely a perfectly
appropriate
solution for 64b porting. At the same time, it is
typical that handles are defined as a void * type, and
so
following the definition their size should follow the
size of the pointer to minimize impact on the related
applications.

This boils down to a solution where the handle has the
size of a pointer, that is 4 or 8 bytes depending on
a platform, but the lower 32b are enough to identify
the handle correctly by the package. There are 2
choices for the upper 32b: they either should always
be set to 0, or should always be sign extended by
the package. The choice is difficult as both
approaches have similar advantages and disadvantages.
The
deciding factor is the pattern of usage by the
customers of the package under discussion.

When the handle values are sign-extended, handling of
all the special values, like ?, is easy. Hence, the
client code requires a minimal facelift. It also
agrees well with using handles in remote RPC calls via
a long
argument. However, when remoting the handle via a
DWORD, a care has to be applied at the 64b side to
sign extend the handle properly. Otherwise the handle
looses sign extension and a comparison like h1 ==
h2 is unreliable (the handles may differ only on upper
32 bits).

When the handle values are zero extended, the special
values like -1 have to be redefined as constants
with appropriate casts and client code modified as
appropriate. This approach agrees very nicely with RPC
remoting via DWORD arguments, which is a typical hack
people use. However, if RPC calls use a long to
represent handle, the care has to be taken to cast the
value properly. Also, if special handle values have
been defined in terms of values perceived as unsigned,
like 0xFFFFFFFF, the user may end up with
comparing a handle with a sign extended 0xFFFFFF
0
 

Author Comment

by:tekel
ID: 2601763
thanks a lot,
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now