473,786 Members | 2,380 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

a question regarding call-by-reference

I am working on a school project, trying to build a simple RPC stub
generator. The idea is that the generator takes a normal python file
with functions defined in it and produces a client and server stub. The
client stub has the same functions defined, but they just connect to
the server and ask it to call the desired functions. The server stub is
a server listening for incoming requests and dispatching them to the
appropriate functions and sending back the results. Extremely simple
and I've gotten it to mostly work, but I have one problem:
call-by-reference parameters. An example:

A function like this:
def sum(a, b):
return a + b

would yield a client stub like this (simplified):
def sum(a, b):
send_message({' funcname': 'sum', 'args': (a, b)})
result = receive_message ()
return result

Now, this works just fine. I get problems when I try to do something
like this:
def add_elm(list):
list.append('el m')
return

Imported normally this would work fine. The list given as a parameter
would be one element larger. But when the stubs are generated, the
function doesn't return anything and the list is appended in the server
and the client-side list is left untouched. At first I thought the
solution was easy, just return the changed parameters and place them in
the parameter variables in the client stub:
def add_elm(list):
send_message({' funcname': 'add_elm', 'args': (list)})
response = receive_message ()
(list) = response.get('a rgs')
return response.get('r esult')

The problem is, this doesn't work. The original list doesn't point to
the changed list. I have been trying to figure this out and it seems
that if I just assign to the list variable it just modifies the local
(to the function) name space, and that those changes aren't reflected
in the list in the original name space.

I believe there are some ways around this, but I haven't found one that
would not require any special handling in either the code calling the
client stub or the original functions. I want to maintain transparency.

etv

Feb 6 '06 #1
6 1477
"enjoying the view" <pp******@gmail .com> wrote in message
news:11******** **************@ o13g2000cwo.goo glegroups.com.. .
I am working on a school project, trying to build a simple RPC stub
generator. The idea is that the generator takes a normal python file
with functions defined in it and produces a client and server stub. The
client stub has the same functions defined, but they just connect to
the server and ask it to call the desired functions. The server stub is
a server listening for incoming requests and dispatching them to the
appropriate functions and sending back the results.

<snip>

One thing you might try is iterating over the arguments and doing special
handling for lists and dicts, which can be updated within the called module.
Using your example (changing 'list' to 'listarg' to avoid confusion):

def add_elm(listarg ):
listarg.append( 'elm')
return

Generate code like:

def add_elm(listarg ):
send_message({' funcname': 'add_elm', 'args': (listarg)})
response = receive_message ()
listarg[:] = response.get('a rgs')[0][:]
return response.get('r esult')

If the listargs get long/complicated, you might be doing a lot of data
copying at the cost of performance (especially since this is a defensive
copy - you don't *know* that the list was updated in the server in the first
place - I guess you could test first with "if response.get('a rgs')[0] !=
listarg:" or something).

For dicts, do:

dictarg.update( response.get('a rgs')[n])

This will be a little cheaper than just total replacement of the contents,
which is what the list [:] slice will do.

But this special-case handling only works for lists and dicts (don't know
how you would handle tuples or scalar variables), you quickly run into other
problems with passing objects. I'm taking you at your word that you are
creating a *simple* RPC stub generator. At this point, you can generate
stubs for methods that do not update their arguments, or for methods that
pass lists or dicts. I've used CORBA in the past, and this is similar to
using a subset of the full parameter functionality, such as using only "in"
parameters (as opposed to "out" or "inout"). That is, instead of defining a
method that modifies its parameter value, have the new value returned by the
function. Python actually helps you here, since it is so easy to pass back
a tuple of values from a function.

This kind of parameter marshalling/unmarshalling gets complicated quickly.
You are already very near the edge of non-intrusiveness on the client and
server sides - to get more features, you'll need to start adding some
aspects of parameter passing mechanisms (such as CORBA's in/out/inout
keywords), and object marshalling conventions (such as requiring objects
that are passed to implement compare() and update() or copy() methods).

-- Paul
Feb 6 '06 #2
enjoying the view wrote:
I am working on a school project, trying to build a simple RPC stub
generator. The idea is that the generator takes a normal python file
with functions defined in it and produces a client and server stub. The
client stub has the same functions defined, but they just connect to
the server and ask it to call the desired functions. The server stub is
a server listening for incoming requests and dispatching them to the
appropriate functions and sending back the results. Extremely simple
and I've gotten it to mostly work, but I have one problem:
call-by-reference parameters. An example:

A function like this:
def sum(a, b):
return a + b

would yield a client stub like this (simplified):
def sum(a, b):
send_message({' funcname': 'sum', 'args': (a, b)})
result = receive_message ()
return result

Now, this works just fine. I get problems when I try to do something
like this:
def add_elm(list):
list.append('el m')
return

Imported normally this would work fine. The list given as a parameter
would be one element larger. But when the stubs are generated, the
function doesn't return anything and the list is appended in the server
and the client-side list is left untouched. At first I thought the
solution was easy, just return the changed parameters and place them in
the parameter variables in the client stub:
def add_elm(list):
send_message({' funcname': 'add_elm', 'args': (list)})
response = receive_message ()
(list) = response.get('a rgs')
return response.get('r esult')

The problem is, this doesn't work. The original list doesn't point to
the changed list. I have been trying to figure this out and it seems
that if I just assign to the list variable it just modifies the local
(to the function) name space, and that those changes aren't reflected
in the list in the original name space.

I believe there are some ways around this, but I haven't found one that
would not require any special handling in either the code calling the
client stub or the original functions. I want to maintain transparency.

etv

I am not an expert, so maybe someone else can provide here a nice tricky
solution, but I am quite sure, that there is no simple way around the
described problem.
The only strategy which comes to my mind in this context is to use for
all function arguments and return values only pickled objects which need
to be unpickled on the other side. Probably some compression algorithm
can help to keep the network traffic down in case large amount of data
must be exchanged.

Claudio
Feb 7 '06 #3
enjoying the view wrote:
Imported normally this would work fine. The list given as a parameter
would be one element larger. But when the stubs are generated, the
function doesn't return anything and the list is appended in the server
and the client-side list is left untouched. At first I thought the
solution was easy, just return the changed parameters and place them in
the parameter variables in the client stub:
def add_elm(list):
send_message({' funcname': 'add_elm', 'args': (list)})
response = receive_message ()
(list) = response.get('a rgs')
return response.get('r esult')

The problem is, this doesn't work. The original list doesn't point to
the changed list. I have been trying to figure this out and it seems
that if I just assign to the list variable it just modifies the local
(to the function) name space, and that those changes aren't reflected
in the list in the original name space.


Try
list[:] = response.get('a rgs')
this will change the value of the list passed in.

Kent
Feb 7 '06 #4
On 6 Feb 2006 10:21:45 -0800, "enjoying the view" <pp******@gmail .com> wrote:
I am working on a school project, trying to build a simple RPC stub
generator. The idea is that the generator takes a normal python file
with functions defined in it and produces a client and server stub. The
client stub has the same functions defined, but they just connect to
the server and ask it to call the desired functions. The server stub is
a server listening for incoming requests and dispatching them to the
appropriate functions and sending back the results. Extremely simple
and I've gotten it to mostly work, but I have one problem:
call-by-reference parameters. An example:

A function like this:
def sum(a, b):
return a + b

would yield a client stub like this (simplified):
def sum(a, b):
send_message({' funcname': 'sum', 'args': (a, b)})
result = receive_message ()
return result

Now, this works just fine. I get problems when I try to do something
like this:
def add_elm(list):
list.append('el m')
return

Imported normally this would work fine. The list given as a parameter
would be one element larger. But when the stubs are generated, the
function doesn't return anything and the list is appended in the server
and the client-side list is left untouched. At first I thought the
solution was easy, just return the changed parameters and place them in
the parameter variables in the client stub:
def add_elm(list):
send_message({' funcname': 'add_elm', 'args': (list)})
response = receive_message () if the response contains an updated list, you can update the content
of the add_elm caller's list by slice assignment, e.g.,
list[:] = response.get(<h owever you get the updated list>')

But you are in really tricky territory here I think. There is any number
of ways to mutate objects via function argument reference. Not just
if they're lists. And lists can be deeply nested, so you could be sending
deep copies of lists across a network, which could involve most of your memory
even if the first level has only a few elements. And if there are side effects besides
the direct mutations, you have additional problems. What if a function accesses
arg.prop and that's a property that keeps count or otherwise tracks instances of something?

The totally general solution is probably impossible. So if I were you I would go back to
the specifier of this problem and negotiate some severe restrictions on assumptions
about arguments (maybe just outlaw direct mutation and access side effects ;-)
(list) = response.get('a rgs')
return response.get('r esult')

The problem is, this doesn't work. The original list doesn't point to
the changed list. I have been trying to figure this out and it seems
that if I just assign to the list variable it just modifies the local
(to the function) name space, and that those changes aren't reflected
in the list in the original name space.

I believe there are some ways around this, but I haven't found one that
would not require any special handling in either the code calling the
client stub or the original functions. I want to maintain transparency.

etv

Good luck ;-)

Regards,
Bengt Richter
Feb 7 '06 #5
Thank you everyone for your helpful replies!

I think the problems that arise with nested and overly large lists and
dictionaries, and difficulties of handling other mutable datatypes will
make my little assignment just too difficult. I'll just specify that
call-by-reference isn't supported and leave it at that.

Between floors. Going down.
Enjoying the view.

Feb 8 '06 #6
Don't send the whole list or parts of the list to the server unless
actually needed!

If the server has to do an append, have the server send back the new
elements to be appended and then do the appending on the client side!

Or

Does the homework specify that the entire mutable type be sent to the
server?
"enjoying the view" <pp******@gmail .com> wrote:
I am working on a school project, trying to build a simple RPC stub
generator. The idea is that the generator takes a normal python file
with functions defined in it and produces a client and server stub. The
client stub has the same functions defined, but they just connect to
the server and ask it to call the desired functions. The server stub is
a server listening for incoming requests and dispatching them to the
appropriate functions and sending back the results. Extremely simple
and I've gotten it to mostly work, but I have one problem:
call-by-reference parameters. An example:

A function like this:
def sum(a, b):
return a + b

would yield a client stub like this (simplified):
def sum(a, b):
send_message({' funcname': 'sum', 'args': (a, b)})
result = receive_message ()
return result

Now, this works just fine. I get problems when I try to do something
like this:
def add_elm(list):
list.append('el m')
return

Imported normally this would work fine. The list given as a parameter
would be one element larger. But when the stubs are generated, the
function doesn't return anything and the list is appended in the server
and the client-side list is left untouched. At first I thought the
solution was easy, just return the changed parameters and place them in
the parameter variables in the client stub:
def add_elm(list):
send_message({' funcname': 'add_elm', 'args': (list)})
response = receive_message ()
(list) = response.get('a rgs')
return response.get('r esult')

The problem is, this doesn't work. The original list doesn't point to
the changed list. I have been trying to figure this out and it seems
that if I just assign to the list variable it just modifies the local
(to the function) name space, and that those changes aren't reflected
in the list in the original name space.

I believe there are some ways around this, but I haven't found one that
would not require any special handling in either the code calling the
client stub or the original functions. I want to maintain transparency.

etv

--
Regards,
Casey
Feb 8 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1919
by: Karl M | last post by:
Hi everyone, I just notice some strange behaviors on the MS C++ compiler regarding struct default constructor, see the example bellow: struct MyStruct { int a; }; class MyClass { public:
3
1423
by: Sarika | last post by:
I have some questions regarding Modal forms and would appreciate if someone could clarify my understanding. (a) I observed that the modal form's Form_Closing event is generated if I set the modal form's Visible property to False or call its Hide method. Is this true? or is it a result of something that I am doing incorrectly? (b) The ShowDialog method halts all other execution in a single threaded program till the modal form is closed,...
77
4040
by: M.B | last post by:
Guys, Need some of your opinion on an oft beaten track We have an option of using "goto" in C language, but most testbooks (even K&R) advice against use of it. My personal experience was that goto sometimes makes program some more cleaner and easy to understand and also quite useful (in error handling cases). So why goto is outlawed from civilized c programmers community. is there any technical inefficiency in that.
3
1734
by: trialproduct2004 | last post by:
Hi all, Can someone tell me how virtual functions works. Like how memory is getting allocated to virtual function. And how to call base class function through derived class pointer. And why virtual function can be access only through pointer. Thanks in advance.
5
1812
by: annhere | last post by:
Hi we have a certain SQL script. From that script we have calls like: DROP FUNCTION A@ call sqlj.remove_jar( 'AXML')@ CALL SQLJ.REFRESH_CLASSES()@ call sqlj.install_jar( 'file:C:\AXML.jar', 'AXML' )@ CALL SQLJ.REFRESH_CLASSES()@ CREATE FUNCTION A(xml VARCHAR(3000),type VARCHAR(3000)) RETURNS VARCHAR(3000) EXTERNAL NAME 'AXML:com.AConvertXML.convertXML' LANGUAGE JAVA
20
1814
by: sam_cit | last post by:
Hi Everyone, I have the following code, int main() { int p = {10,20,30,40,50}; int *i = &p; printf("before : %p\n",(void*)i); printf("1 %d %d\n",*++i,*i++);
4
2313
by: Benny Van | last post by:
Hi all! I have a question regarding a windows operating system function: I was asked to write a small program for a homework to display the user name and computer name and the system time out to a console window: the display would be like: Hello XXX(user) Today is XXX(date) The Time is XXX(current system time) I was asked to use a Windows System Call---void GetLocalTime(SYSTIME
1
1750
by: Jim Flanagan | last post by:
Hello - I am in need of more help regarding an approach to accomplishing the following: We have a need to change the Volume serial numbers of a bunch of preprogrammed IDE Solid State Drive modules. The modules have been duplicated and thus the need to change the serial number on each one. My approach is to use a USB to IDE adapter cable and write a C# routine which will automate the writing of the serial #. At this point, I have a...
5
1587
by: Philip Potter | last post by:
I have a somewhat flippant question regarding undefined behaviour. Does an operation which invokes undefined behaviour affect the whole program, or are earlier statements guaranteed to execute correctly? For example: #include <stdio.h> int main(void) { int i;
4
2064
by: Pranav | last post by:
Hello All, I have a simple question regarding the definition of abstract class, IIRC , Abstract class is one which contains virtual function declaration and other variables and no object of this class is created directly. If this is the case why don't we hide the constructor of abstract class into protected region? So that only object which inherits it can call the ctor of abstract class. In this way no one can create the object of...
0
9492
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10360
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10163
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9960
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8988
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7510
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
1
4064
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3668
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2894
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.