Function pointers (callbacks) in Java

E

exquisitus

I have legacy code in C that I am porting to java. The code makes
extensive use of function pointers (callbacks). An example is as follows:

typedef double (*PFUNC)(PricingParam const *) ;

typedef struct
{
int model_id ;
PFUNC prc_func ;
} PRICING_ENGINE ;

Does anyone have any ideas as to how I can go about implementing this in
Java?. The structure is acting as a lookup table to match models with
the appropriate pricing function (I believe I can use a hashtable to do
this - but I do not know how to store function pointers in a hashtable).

Many thanks
 
S

shakah

I've used interfaces for that in the past, e.g. something like:

PricingFunction.java
====================
public interface PricingFunction {
public double calcPrice(PricingParam pp) ;
}

An implementation of it, maybe PFSimple.java:
=============================================
public class PFSimple
implements PricingFunction {

public PFSimple(/*args*/) {
...
}

public double calcPrice(PricingParam pp) {
...
}
}

Your struct, maybe PricingEngine.java:
======================================
public class PricingEngine {
private int nModelId_ ;
private PricingFunction pf_ ;

public PricingEngine(int nModelId, PricingFunction pf) {
nModelId_ = nModelId ;
pf_ = pf ;
}

public double doPricing(PricingParam pp) {
return pf_.calcPrice(pp) ;
}

// ...etc
}

Using it:
=========
PricingEngine pe = new PricingEngine(1, new PFSimple()) ;
 
E

exquisitus

Thank you very much shakah. This is exactly what I was looking for. Many
thanks, once again.
 
J

Joseph Dionne

exquisitus said:
I have legacy code in C that I am porting to java. The code makes
extensive use of function pointers (callbacks). An example is as follows:

typedef double (*PFUNC)(PricingParam const *) ;

typedef struct
{
int model_id ;
PFUNC prc_func ;
} PRICING_ENGINE ;

Does anyone have any ideas as to how I can go about implementing this in
Java?. The structure is acting as a lookup table to match models with
the appropriate pricing function (I believe I can use a hashtable to do
this - but I do not know how to store function pointers in a hashtable).

Many thanks

You can also use reflection to pass any method for "call back."

import java.lang.Class;
import java.lang.Exception;
import java.lang.reflect.Method;

public class jMethod extends Exception
{
public class MethodCallback extends Exception
{
private Object cbObject = null;
private Method callBack = null;

public MethodCallback(Object cbObj,Method cbMethod)
{
if (cbMethod instanceof Method)
{
cbObject = cbObj;
callBack = cbMethod;
}
}

public void run() throws Exception
{
doCallBack("a call back");
}

public void doCallBack(String msg) throws Exception
{
Object[] args = new Object[] { msg };

callBack.invoke(cbObject,args);
}
}

public static void main(String[] args) throws Exception
{
jMethod method = new jMethod();

method.run();
}

public void run() throws Exception
{
Class c = this.getClass();
Class[] parms = new Class[] { String.class };

MethodCallback callMeBack = new MethodCallback(
(Object)this,this.getClass().getMethod("callBackHere",parms));

callMeBack.run();
}

public void callBackHere(String msg)
{
System.out.println("jMethod.callBackHere got " + msg);
}
}
 
B

Bryce

You can also use reflection to pass any method for "call back."

Pickup the latest Java Developers Journal. It has an article on using
the Method class to simulate Delegates.
 
D

Dimitri Maziuk

Joseph Dionne sez:
You can also use reflection to pass any method for "call back."
[ ~ 30 LOC snipped ]

All you really have to do is wrap your pricing functions in
classes. You have to do that anyway since you can't have free
functions in Java. Make them extend a base class or implement
interface that specifies prc_func( PricingParam p ) method,
then get them out hashtable as base class/interface.
(Note that you'll lose the const'ness of PricingParam in Java.)

(Of course you can also put them in one class and have a big
switch( model_id ) statement.)

Dima
 
J

JSmith

IMHO, the closest you can 'functionally' get to C-like function pointers in
Java is using an array of indexed command objects that all implement from an
interface/extend an abstract class.

Of course you will have to customize each object type behavoirs based on
its index ...

No silly switch statements and similar conditional ones

They have told you about strategies that 'syntactically look like' C-like
function pointers, but in reallity Java was deviced by design, among may
other things, to avoid exactly what you are looking for
 
D

Dimitri Maziuk

JSmith sez:
IMHO, the closest you can 'functionally' get to C-like function pointers in
Java is using an array of indexed command objects that all implement from an
interface/extend an abstract class.

Of course you will have to customize each object type behavoirs based on
its index ...

No silly switch statements and similar conditional ones

Silly switch statement or its equivalent will work if your
command map is static.

Typically, function pointers are used for three reasons:
user-supplied callbacks, dynamic (run-time extensible)
command maps, poor man's late binding.

In the first case you'll usually stick all callbacks in one
class (see e.g. SAX content handler; libxml used function
pointers last I looked).

In the second case you'll use "functors": one-method objects.

Proper OO solution for the third case is to redesign the whole
thing to use inheritance.

Dima
 
J

Joseph Dionne

JSmith said:
IMHO, the closest you can 'functionally' get to C-like function pointers in
Java is using an array of indexed command objects that all implement from an
interface/extend an abstract class.

Of course you will have to customize each object type behavoirs based on
its index ...

No silly switch statements and similar conditional ones

They have told you about strategies that 'syntactically look like' C-like
function pointers, but in reallity Java was deviced by design, among may
other things, to avoid exactly what you are looking for

IMHO, while syntactically a java app will not resemble a c app, one can
easily replicate function call backs in Java. Example follows.

// File: jCallbacks.java
import java.lang.Class;
import java.lang.Exception;
import java.lang.reflect.Method;

abstract class CallBackObject extends Exception
{
private Object cbObject = null;
private Method cbMethod = null;
private Object[] cbArgs = null;

protected CallBackObject() {};

protected CallBackObject(Object cbo,String cbmname,Class[] cbp)
throws Exception
{
setCallBackObject(cbo);
setCallBackMethod(cbmname,cbp);
}

protected void setCallBackObject(Object cbo)
throws Exception
{
cbObject = cbo;
}

protected void setCallBackMethod(String cbmname,Class[] cbp)
throws Exception
{
cbMethod = cbObject.getClass().getMethod(cbmname,cbp);
}

protected void setCallBackArgs(Object[] args)
throws Exception
{
cbArgs = args;
}

public void doCallBack() throws Exception
{
cbMethod.invoke(cbObject,cbArgs);
}

public void doCallBack(Object[] args) throws Exception
{
cbMethod.invoke(cbObject,args);
}
}

// CbExample could be an Observer of Inventory changes.
class CbExample extends CallBackObject
{
private String descr = null;
private Float price = null;
private Integer stock = null;

public CbExample(String what)
{
descr = what;
}

public void monitor() { monitor(descr); }

private void monitor(String what)
{
// Key into DB
descr = what;

// Observed event triggered, envision data from DB
price = new Float(9.99);
stock = new Integer(3);

try {
setCallBackArgs(new Object[] {descr,price,stock});
doCallBack();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}

public class jCallbacks extends Exception
{
public static jCallbacks main = new jCallbacks();
public CbExample trigger = null;

public static void main(String[] args) throws Exception
{
main.begin();
}

public void begin() throws Exception
{
trigger = new CbExample("Widgets");

trigger.setCallBackObject(this);
trigger.setCallBackMethod("callBackHere",
new Class[] {String.class,Float.class,Integer.class});

trigger.monitor();
}

public void callBackHere(String desc,Float amount,Integer quantity)
{
Float total = new Float(quantity.intValue() * amount.floatValue());

System.out.println(desc + " for " + amount + " each, total " +
total);
}
}

joseph
 
T

Tim Tyler

Joseph Dionne said:
exquisitus wrote:

You can also use reflection to pass any method for "call back."

Yes - but that violates the principle of not using Java's reflection,
mechanisms - except when you have to ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top