New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CBlock How to call function from dll Windows #1659

Closed
piotrkardasz opened this Issue Jun 30, 2018 · 4 comments

Comments

Projects
None yet
2 participants
@piotrkardasz
Copy link

piotrkardasz commented Jun 30, 2018

I would like to know it's possible to call any function from dll like this?

and next question is how to declare functions in cblock which returns string from dll function because when i try to #include compiler throw errors.

namespace Newapp;

%{
// top statement before class, add to after headers
// test include .h
#include "core/stdafx.h"
#include <Windows.h>
#include "kernel/require.h"


typedef int(__stdcall *msgbox)(HWND, LPCSTR, LPCSTR, UINT);
typedef HWND(__stdcall *actiwin)(void);

int GetHandleA(){

	HMODULE dll = LoadLibrary(L"user32.dll");
	if (NULL != dll)
	{
		actiwin func = (actiwin)GetProcAddress(dll, "GetForegroundWindow");

		if (func != NULL)
		{
			HWND  ret = func();
			return (int)ret;
		}
		else return -2;
	}
	else{
		return -1;
	}
}
}%


class Greeting
{

	public static function dllcall()
	{
		long ret = 0;
		%{
			HMODULE dll = LoadLibrary(L"user32.dll");
			if (NULL != dll)
			{
				msgbox func = (msgbox)GetProcAddress(dll, "MessageBoxA");

				if (func != NULL)
				{
					int ret = func(0, "text", "Textr1", MB_OK);
				}
				else {
					
				}
			}
		}%
		return ret;
	}

	
	public static function getHandlerEx()
        {
            long a = 10;

            %{
            a = GetHandleA();
            }%

            return a;
        }
			
}
@sergeyklay

This comment has been minimized.

Copy link
Member

sergeyklay commented Jun 30, 2018

To call any c-function you can embed c-code in tags, like so: %{ // c-code }%. (check https://github.com/phalcon/zephir/blob/master/test/cblock.zep as an example). A bit more elegant, but also more work, are custom optimizers. An ‘optimizer’ works like an interceptor for function calls. An ‘optimizer’ replaces the call for the function in the PHP userland by direct C-calls which are faster and have a lower overhead improving performance. Please check #21 (comment) and https://docs.zephir-lang.com/en/latest/optimizers.html.

To return a string from your C-function you will may have something like this:

// RETURN_MM_STRING(str);

RETVAL_STRING(str);
ZEPHIR_MM_RESTORE();
return;

Please take a look at https://github.com/phalcon/cphalcon/blob/master/phalcon/kernel.zep

@piotrkardasz

This comment has been minimized.

Copy link

piotrkardasz commented Jun 30, 2018

Thanks for reply I'm trying to build optimizer like in docs.
But while i trying do that php while parse test.php crash
Please, Could You look at
https://github.com/piotrkardasz/zaphirsimple.git
PHP 7.1.19 (cli) ( NTS MSVC14 (Visual C++ 2015) x64 )@w10
test.php throw this or crash it look like variable overflow problem?
start 0 -685785296 end

@sergeyklay

This comment has been minimized.

Copy link
Member

sergeyklay commented Jun 30, 2018

@piotrkardasz The main mistake is to pass zval as int . Just fixed your example.

ext/my-fibonacci.c
--- a/ext/my-fibonacci.c
+++ b/ext/my-fibonacci.c
@@ -1,4 +1,5 @@
-int fibonacci(long n) {
+unsigned int fibonacci(unsigned int n) {
         if (n < 2) return n;
-        else return fibonacci(n - 2) + fibonacci(n - 1);
+
+        return fibonacci(n - 1) + fibonacci(n - 2);
 }
ext/my-fibonacci.h
--- a/ext/my-fibonacci.h
+++ b/ext/my-fibonacci.h
@@ -5,4 +5,4 @@
 #include "php.h"
 #include "php_ext.h"
 
-int fibonacci(int n);
+unsigned int fibonacci(unsigned int n);
optimizers/FibonacciOptimizer.php
--- a/optimizers/FibonacciOptimizer.php
+++ b/optimizers/FibonacciOptimizer.php
@@ -6,16 +6,69 @@ use Zephir\Call;
 use Zephir\CompilationContext;
 use Zephir\CompiledExpression;
 use Zephir\Optimizers\OptimizerAbstract;
-use Zephir\CompilerException;
+use Zephir\Compiler\CompilerException;
 
 class FibonacciOptimizer extends OptimizerAbstract
-
-{   
+{
     public function optimize(array $expression, Call $call, CompilationContext $context)
     {
+    	if (!isset($expression['parameters']) || count($expression['parameters']) > 1) {
+        	throw new CompilerException("'fibonacci' requires one parameter", $expression);
+        }
+
+        $call->processExpectedReturn($context);
+
         $context->headersManager->add('my-fibonacci');
 
-        $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression);
-        return new CompiledExpression('int', 'fibonacci(' . $resolvedParams[0] . ')', $expression);
+        $resolvedParams = $call->getResolvedParamsAsExpr($expression['parameters'], $context, $expression);
+        $compiledExpression = $resolvedParams[0];
+
+        switch ($compiledExpression->getType()) {
+            case 'int':
+                return $this->passNativeFCall($compiledExpression, $expression);
+                break;
+            case 'variable':
+                $variable = $context->symbolTable->getVariable($compiledExpression->getCode());
+                switch ($variable->getType()) {
+                    case 'int':
+                        return $this->passNativeFCall($compiledExpression, $expression);
+                        break;
+                    case 'variable':
+                        return new CompiledExpression(
+                            'uint',
+                            'fibonacci(' . $context->backend->getVariableCode($variable) . ' TSRMLS_CC)',
+                            $expression
+                        );
+                        break;
+                }
+                break;
+        }
+
+        return false;
+    }
+
+    /**
+     * @param CompiledExpression $compiledExpression
+     * @param array $expression
+     * @return CompiledExpression
+     */
+    protected function passNativeFCall($compiledExpression, $expression)
+    {
+        return new CompiledExpression(
+            'uint',
+            'fibonacci(' . $compiledExpression->getCode() . ')',
+            $expression
+        );
     }
 }
samples/math.zep
--- a/samples/math.zep
+++ b/samples/math.zep
@@ -15,7 +15,7 @@ class Math
 	
 	public static function someMethod()
     {
-        int a;
+        var a;
 
         let a = fibonacci(40);
         return a;

Output

$ php test.php
start 
0
102334155
end
@sergeyklay

This comment has been minimized.

Copy link
Member

sergeyklay commented Jun 30, 2018

We only accept bug reports, new feature requests and pull requests in GitHub. For questions regarding the usage of the Zephir Language, support requests, and questions like this please visit the official forums.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment