Dear fellow programmers,
Currently I am working on implementing a Microsoft RPC server / client program on Windows. Using nmake, I managed to compile the client-side of the program, but the server-side gives some problems.
The following relevant files are:
Example1.idl
[
uuid(30f190d8-b966-4619-8f45-72342e6ad058),
version(1.0)
]
interface Example1
{
void Output(
[in, string] const char* szOutput
);
}
Example1.acf
[
implicit_handle(handle_t hExample1Binding)
]
interface Example1
{
}
Example1Server.cpp
#include <iostream>
#include "Example1.h"
void Output(
/* [string][in] */ const char* szOutput)
{
std::cout << szOutput << '\n';
}
RPC_STATUS CALLBACK SecurityCallback(RPC_IF_HANDLE, void*)
{
return RPC_S_OK;
}
int main()
{
RPC_STATUS status;
status = RpcServerUseProtseqEp(
reinterpret_cast<unsigned char*>("ncacn_ip_tcp"),
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
reinterpret_cast<unsigned char*>("4747"),
NULL);
if (status) exit(status);
status = RpcServerRegisterIf2(
Example1_v1_0_s_ifspec,
NULL,
NULL,
RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH,
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
(unsigned)-1,
SecurityCallback);
if (status) exit(status);
status = RpcServerListen(
1,
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
FALSE);
if (status) exit(status);
}
void* __RPC_USER midl_user_allocate(size_t size)
{
return malloc(size);
}
void __RPC_USER midl_user_free(void* p)
{
free(p);
}
makefile
!include <Win32.mak>
# all : Example1Client Example1Server
all : Example1Server
# # Make the client side application Example1Client. This works without compilation problems.
# Example1Client : Example1Client.exe
# Example1Client.exe : Example1Client.obj Example1_c.obj
# $(link) $(linkdebug) $(conflags) -out:Example1Client.exe \
# Example1Client.obj Example1_c.obj \
# rpcrt4.lib $(conlibs)
# # Example1Client main program
# Example1Client.obj : Example1Client.cpp Example1.h
# $(cc) $(cdebug) $(cflags) $(cvars) $*.cpp
# # Example1Client stub
# Example1_c.obj : Example1_c.c Example1.h
# $(cc) $(cdebug) $(cflags) $(cvars) $*.c
# Make the server side application Example1Server
Example1Server : Example1Server.exe
Example1Server.exe : Example1Server.obj Example1_s.obj
$(link) $(linkdebug) $(conflags) -out:Example1Server.exe \
Example1Server.obj Example1_s.obj \
rpcrt4.lib $(conlibsmt)
# Example1Server main program
Example1Server.obj : Example1Server.cpp Example1.h
$(cc) $(cdebug) $(cflags) $(cvarsmt) $*.cpp
# Example1Server stub file
Example1_s.obj : Example1_s.c Example1.h
$(cc) $(cdebug) $(cflags) $(cvarsmt) $*.c
# Stubs and header file from the IDL file
Example1.h Example1_c.c Example1_s.c : Example1.idl Example1.acf
midl Example1.idl
Here, Win32.mak
is the windows32 file specifying generic settings for compiling with nmake on the Windows machine.
I ran the following commands (using the developer tools command prompt, Visual Studio 2015):
midl Example1.idl
Using the midl command, the header file Example1.h
is generated, along with the stub files Example1_s.c
and Example1_c.c
.
Example1_s.c:
/* this ALWAYS GENERATED file contains the RPC server stubs */
/* File created by MIDL compiler version 8.01.0620 */
/* at Mon Jan 18 19:14:07 2038
*/
/* Compiler settings for Example1.idl:
Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0620
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
/* @@MIDL_FILE_HEADING( ) */
#if defined(_M_AMD64)
#pragma warning( disable: 4049 ) /* more than 64k source lines */
#if _MSC_VER >= 1200
#pragma warning(push)
#endif
#pragma warning( disable: 4211 ) /* redefine extern to static */
#pragma warning( disable: 4232 ) /* dllimport identity*/
#pragma warning( disable: 4024 ) /* array to pointer mapping*/
#pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */
#pragma optimize("", off )
#include <string.h>
#include "Example1.h"
#define TYPE_FORMAT_STRING_SIZE 7
#define PROC_FORMAT_STRING_SIZE 33
#define EXPR_FORMAT_STRING_SIZE 1
#define TRANSMIT_AS_TABLE_SIZE 0
#define WIRE_MARSHAL_TABLE_SIZE 0
typedef struct _Example1_MIDL_TYPE_FORMAT_STRING
{
short Pad;
unsigned char Format[ TYPE_FORMAT_STRING_SIZE ];
} Example1_MIDL_TYPE_FORMAT_STRING;
typedef struct _Example1_MIDL_PROC_FORMAT_STRING
{
short Pad;
unsigned char Format[ PROC_FORMAT_STRING_SIZE ];
} Example1_MIDL_PROC_FORMAT_STRING;
typedef struct _Example1_MIDL_EXPR_FORMAT_STRING
{
long Pad;
unsigned char Format[ EXPR_FORMAT_STRING_SIZE ];
} Example1_MIDL_EXPR_FORMAT_STRING;
static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax =
{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}};
extern const Example1_MIDL_TYPE_FORMAT_STRING Example1__MIDL_TypeFormatString;
extern const Example1_MIDL_PROC_FORMAT_STRING Example1__MIDL_ProcFormatString;
extern const Example1_MIDL_EXPR_FORMAT_STRING Example1__MIDL_ExprFormatString;
/* Standard interface: Example1, ver. 1.0,
GUID={0x30f190d8,0xb906,0x4699,{0x8f,0x45,0x72,0x33,0x2e,0x6a,0xd0,0x58}} */
extern const MIDL_SERVER_INFO Example1_ServerInfo;
extern const RPC_DISPATCH_TABLE Example1_v1_0_DispatchTable;
static const RPC_SERVER_INTERFACE Example1___RpcServerInterface =
{
sizeof(RPC_SERVER_INTERFACE),
{{0x30f190d8,0xb906,0x4699,{0x8f,0x45,0x72,0x33,0x2e,0x6a,0xd0,0x58}},{1,0}},
{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}},
(RPC_DISPATCH_TABLE*)&Example1_v1_0_DispatchTable,
0,
0,
0,
&Example1_ServerInfo,
0x04000000
};
RPC_IF_HANDLE Example1_v1_0_s_ifspec = (RPC_IF_HANDLE)& Example1___RpcServerInterface;
extern const MIDL_STUB_DESC Example1_StubDesc;
#if !defined(__RPC_WIN64__)
#error Invalid build platform for this stub.
#endif
#if !(TARGET_IS_NT50_OR_LATER)
#error You need Windows 2000 or later to run this stub because it uses these features:
#error /robust command line switch.
#error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems.
#error This app will fail with the RPC_X_WRONG_STUB_VERSION error.
#endif
static const Example1_MIDL_PROC_FORMAT_STRING Example1__MIDL_ProcFormatString =
{
0,
{
/* Procedure Output */
0x32, /* FC_BIND_PRIMITIVE */
0x48, /* Old Flags: */
/* 2 */ NdrFcLong( 0x0 ), /* 0 */
/* 6 */ NdrFcShort( 0x0 ), /* 0 */
/* 8 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */
/* 10 */ NdrFcShort( 0x0 ), /* 0 */
/* 12 */ NdrFcShort( 0x0 ), /* 0 */
/* 14 */ 0x42, /* Oi2 Flags: clt must size, has ext, */
0x1, /* 1 */
/* 16 */ 0xa, /* 10 */
0x1, /* Ext Flags: new corr desc, */
/* 18 */ NdrFcShort( 0x0 ), /* 0 */
/* 20 */ NdrFcShort( 0x0 ), /* 0 */
/* 22 */ NdrFcShort( 0x0 ), /* 0 */
/* 24 */ NdrFcShort( 0x0 ), /* 0 */
/* Parameter szOutput */
/* 26 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */
/* 28 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */
/* 30 */ NdrFcShort( 0x4 ), /* Type Offset=4 */
0x0
}
};
static const Example1_MIDL_TYPE_FORMAT_STRING Example1__MIDL_TypeFormatString =
{
0,
{
NdrFcShort( 0x0 ), /* 0 */
/* 2 */
0x11, 0x8, /* FC_RP [simple_pointer] */
/* 4 */
0x22, /* FC_C_CSTRING */
0x5c, /* FC_PAD */
0x0
}
};
static const unsigned short Example1_FormatStringOffsetTable[] =
{
0
};
static const MIDL_STUB_DESC Example1_StubDesc =
{
(void *)& Example1___RpcServerInterface,
MIDL_user_allocate,
MIDL_user_free,
0,
0,
0,
0,
0,
Example1__MIDL_TypeFormatString.Format,
1, /* -error bounds_check flag */
0x50002, /* Ndr library version */
0,
0x801026c, /* MIDL Version 8.1.620 */
0,
0,
0, /* notify & notify_flag routine table */
0x1, /* MIDL flag */
0, /* cs routines */
0, /* proxy/server info */
0
};
static const RPC_DISPATCH_FUNCTION Example1_table[] =
{
NdrServerCall2,
0
};
static const RPC_DISPATCH_TABLE Example1_v1_0_DispatchTable =
{
1,
(RPC_DISPATCH_FUNCTION*)Example1_table
};
static const SERVER_ROUTINE Example1_ServerRoutineTable[] =
{
(SERVER_ROUTINE)Output
};
static const MIDL_SERVER_INFO Example1_ServerInfo =
{
&Example1_StubDesc,
Example1_ServerRoutineTable,
Example1__MIDL_ProcFormatString.Format,
Example1_FormatStringOffsetTable,
0,
0,
0,
0};
#if _MSC_VER >= 1200
#pragma warning(pop)
#endif
#endif /* defined(_M_AMD64)*/
Example1.h
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 8.01.0620 */
/* at Mon Jan 18 19:14:07 2038
*/
/* Compiler settings for Example1.idl:
Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0620
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
/* @@MIDL_FILE_HEADING( ) */
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif /* __RPCNDR_H_VERSION__ */
#ifndef __Example1_h__
#define __Example1_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
#ifdef __cplusplus
extern "C"{
#endif
#ifndef __Example1_INTERFACE_DEFINED__
#define __Example1_INTERFACE_DEFINED__
/* interface Example1 */
/* [implicit_handle][version][uuid] */
void Output(
/* [string][in] */ const unsigned char *szOutput);
extern handle_t hExample1Binding;
extern RPC_IF_HANDLE Example1_v1_0_c_ifspec;
extern RPC_IF_HANDLE Example1_v1_0_s_ifspec;
#endif /* __Example1_INTERFACE_DEFINED__ */
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif
Next, running nmake
, the following error is displayed:
link /DEBUG /DEBUGTYPE:cv /INCREMENTAL:NO /NOLOGO -subsystem:console,5.0 -out:Example1Server.exe ExampleServer.obj Example1_s.obj rpcrt4.lib kernel32.lib ws2_32.lib mswsock.lib advapi32.lib
LINK : warning LNK4010: invalid subsytem version number 5.0; default subsystem version assumed
Example1_s.obj : error LNK2001: unresolved external symbol Output
Example1Server.exe : fatal error LNK1120: 1 unresolved externals
My understanding is that the Output function is not found in Example1_s.obj. This object file is created from Example1_s.c, which is generated automatically with the midl
command.
I have tried various things, such as including the header file to the link to the Example1Server, modifying the output function such that it resembles the output function in the acf file and looking around on the internet for solutions.
Most solutions found to the problems on the internet were centered around including the rpcrt4.lib, which is sadly not the solution to my problem.
I'm quite stuck at the moment, and would really appreciate it if someone can help me out in solving the LNK2001 error. Thanks in advance.
The Output function's parameter keyword in the Example1Server.cpp should be same as function declaration in the MIDL generated header file Example1.h
unsigned is missing in your case.
It should be as below in Example1Server.cpp